mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-29 23:42:08 +00:00
1484 lines
No EOL
42 KiB
C++
1484 lines
No EOL
42 KiB
C++
/*
|
|
** zcc_expr.cpp
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright -2016 Randy Heit
|
|
** All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
**
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
*/
|
|
|
|
#include "dobject.h"
|
|
#include "sc_man.h"
|
|
#include "filesystem.h"
|
|
#include "cmdlib.h"
|
|
#include "m_argv.h"
|
|
#include "v_text.h"
|
|
#include "version.h"
|
|
#include "zcc_parser.h"
|
|
#include "zcc_compile.h"
|
|
|
|
|
|
TArray<FString> Includes;
|
|
TArray<FScriptPosition> IncludeLocs;
|
|
|
|
static FString ResolveIncludePath(const FString &path,const FString &lumpname){
|
|
if (path.IndexOf("./") == 0 || path.IndexOf("../") == 0) // relative path resolving
|
|
{
|
|
auto start = lumpname.LastIndexOf(":"); // find find separator between wad and path
|
|
|
|
auto end = lumpname.LastIndexOf("/"); // find last '/'
|
|
|
|
// it's a top-level file, if it's a folder being loaded ( /xxx/yyy/:whatever.zs ) end is before than start, or if it's a zip ( xxx.zip:whatever.zs ) end would be -1
|
|
bool topLevelFile = start > end ;
|
|
|
|
FString fullPath = topLevelFile ? FString {} : lumpname.Mid(start + 1, end - start - 1); // get path from lumpname (format 'wad:filepath/filename')
|
|
|
|
if (start != -1)
|
|
{
|
|
FString relativePath = path;
|
|
if (relativePath.IndexOf("./") == 0) // strip initial marker
|
|
{
|
|
relativePath = relativePath.Mid(2);
|
|
}
|
|
|
|
bool pathOk = true;
|
|
|
|
while (relativePath.IndexOf("../") == 0) // go back one folder for each '..'
|
|
{
|
|
relativePath = relativePath.Mid(3);
|
|
auto slash_index = fullPath.LastIndexOf("/");
|
|
if (slash_index != -1) {
|
|
fullPath = fullPath.Mid(0, slash_index);
|
|
} else {
|
|
pathOk = false;
|
|
break;
|
|
}
|
|
}
|
|
if (pathOk) // if '..' parsing was successful
|
|
{
|
|
return topLevelFile ? relativePath : fullPath + "/" + relativePath;
|
|
}
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
|
|
static FString ZCCTokenName(int terminal);
|
|
void AddInclude(ZCC_ExprConstant *node)
|
|
{
|
|
assert(node->Type == TypeString);
|
|
|
|
FScriptPosition pos(*node);
|
|
|
|
FString path = ResolveIncludePath(*node->StringVal, pos.FileName.GetChars());
|
|
|
|
if (Includes.Find(path) >= Includes.Size())
|
|
{
|
|
Includes.Push(path);
|
|
IncludeLocs.Push(pos);
|
|
}
|
|
}
|
|
|
|
#include "zcc-parse.h"
|
|
#include "zcc-parse.c"
|
|
|
|
struct TokenMapEntry
|
|
{
|
|
int16_t TokenType;
|
|
uint16_t TokenName;
|
|
TokenMapEntry(int16_t a, uint16_t b)
|
|
: TokenType(a), TokenName(b)
|
|
{ }
|
|
};
|
|
static TMap<int16_t, TokenMapEntry> TokenMap;
|
|
static int16_t BackTokenMap[YYERRORSYMBOL]; // YYERRORSYMBOL immediately follows the terminals described by the grammar
|
|
|
|
#define TOKENDEF2(sc, zcc, name) { TokenMapEntry tme(zcc, name); TokenMap.Insert(sc, tme); } BackTokenMap[zcc] = sc
|
|
#define TOKENDEF(sc, zcc) TOKENDEF2(sc, zcc, NAME_None)
|
|
|
|
static void InitTokenMap()
|
|
{
|
|
TOKENDEF ('=', ZCC_EQ);
|
|
TOKENDEF (TK_MulEq, ZCC_MULEQ);
|
|
TOKENDEF (TK_DivEq, ZCC_DIVEQ);
|
|
TOKENDEF (TK_ModEq, ZCC_MODEQ);
|
|
TOKENDEF (TK_AddEq, ZCC_ADDEQ);
|
|
TOKENDEF (TK_SubEq, ZCC_SUBEQ);
|
|
TOKENDEF (TK_LShiftEq, ZCC_LSHEQ);
|
|
TOKENDEF (TK_RShiftEq, ZCC_RSHEQ);
|
|
TOKENDEF (TK_URShiftEq, ZCC_URSHEQ);
|
|
TOKENDEF (TK_AndEq, ZCC_ANDEQ);
|
|
TOKENDEF (TK_OrEq, ZCC_OREQ);
|
|
TOKENDEF (TK_XorEq, ZCC_XOREQ);
|
|
TOKENDEF ('?', ZCC_QUESTION);
|
|
TOKENDEF (':', ZCC_COLON);
|
|
TOKENDEF ('@', ZCC_ATSIGN);
|
|
TOKENDEF (TK_OrOr, ZCC_OROR);
|
|
TOKENDEF (TK_AndAnd, ZCC_ANDAND);
|
|
TOKENDEF (TK_Eq, ZCC_EQEQ);
|
|
TOKENDEF (TK_Neq, ZCC_NEQ);
|
|
TOKENDEF (TK_ApproxEq, ZCC_APPROXEQ);
|
|
TOKENDEF ('<', ZCC_LT);
|
|
TOKENDEF ('>', ZCC_GT);
|
|
TOKENDEF (TK_Leq, ZCC_LTEQ);
|
|
TOKENDEF (TK_Geq, ZCC_GTEQ);
|
|
TOKENDEF (TK_LtGtEq, ZCC_LTGTEQ);
|
|
TOKENDEF (TK_Is, ZCC_IS);
|
|
TOKENDEF (TK_DotDot, ZCC_DOTDOT);
|
|
TOKENDEF (TK_Ellipsis, ZCC_ELLIPSIS);
|
|
TOKENDEF ('|', ZCC_OR);
|
|
TOKENDEF ('^', ZCC_XOR);
|
|
TOKENDEF ('&', ZCC_AND);
|
|
TOKENDEF (TK_LShift, ZCC_LSH);
|
|
TOKENDEF (TK_RShift, ZCC_RSH);
|
|
TOKENDEF (TK_URShift, ZCC_URSH);
|
|
TOKENDEF ('-', ZCC_SUB);
|
|
TOKENDEF ('+', ZCC_ADD);
|
|
TOKENDEF ('*', ZCC_MUL);
|
|
TOKENDEF ('/', ZCC_DIV);
|
|
TOKENDEF ('%', ZCC_MOD);
|
|
TOKENDEF (TK_Cross, ZCC_CROSSPROD);
|
|
TOKENDEF (TK_Dot, ZCC_DOTPROD);
|
|
TOKENDEF (TK_MulMul, ZCC_POW);
|
|
TOKENDEF (TK_Incr, ZCC_ADDADD);
|
|
TOKENDEF (TK_Decr, ZCC_SUBSUB);
|
|
TOKENDEF ('.', ZCC_DOT);
|
|
TOKENDEF ('(', ZCC_LPAREN);
|
|
TOKENDEF (')', ZCC_RPAREN);
|
|
TOKENDEF (TK_ColonColon, ZCC_SCOPE);
|
|
TOKENDEF (';', ZCC_SEMICOLON);
|
|
TOKENDEF (',', ZCC_COMMA);
|
|
TOKENDEF (TK_Class, ZCC_CLASS);
|
|
TOKENDEF (TK_Abstract, ZCC_ABSTRACT);
|
|
TOKENDEF (TK_Native, ZCC_NATIVE);
|
|
TOKENDEF (TK_Action, ZCC_ACTION);
|
|
TOKENDEF (TK_Replaces, ZCC_REPLACES);
|
|
TOKENDEF (TK_Static, ZCC_STATIC);
|
|
TOKENDEF (TK_Private, ZCC_PRIVATE);
|
|
TOKENDEF (TK_Protected, ZCC_PROTECTED);
|
|
TOKENDEF (TK_Latent, ZCC_LATENT);
|
|
TOKENDEF (TK_Virtual, ZCC_VIRTUAL);
|
|
TOKENDEF (TK_VarArg, ZCC_VARARG);
|
|
TOKENDEF (TK_UI, ZCC_UI);
|
|
TOKENDEF (TK_Play, ZCC_PLAY);
|
|
TOKENDEF (TK_ClearScope, ZCC_CLEARSCOPE);
|
|
TOKENDEF (TK_VirtualScope, ZCC_VIRTUALSCOPE);
|
|
TOKENDEF (TK_Override, ZCC_OVERRIDE);
|
|
TOKENDEF (TK_Final, ZCC_FINAL);
|
|
TOKENDEF (TK_Meta, ZCC_META);
|
|
TOKENDEF (TK_Deprecated, ZCC_DEPRECATED);
|
|
TOKENDEF (TK_Version, ZCC_VERSION);
|
|
TOKENDEF (TK_ReadOnly, ZCC_READONLY);
|
|
TOKENDEF (TK_Internal, ZCC_INTERNAL);
|
|
TOKENDEF ('{', ZCC_LBRACE);
|
|
TOKENDEF ('}', ZCC_RBRACE);
|
|
TOKENDEF (TK_Struct, ZCC_STRUCT);
|
|
TOKENDEF (TK_Property, ZCC_PROPERTY);
|
|
TOKENDEF (TK_FlagDef, ZCC_FLAGDEF);
|
|
TOKENDEF (TK_Mixin, ZCC_MIXIN);
|
|
TOKENDEF (TK_Transient, ZCC_TRANSIENT);
|
|
TOKENDEF (TK_Enum, ZCC_ENUM);
|
|
TOKENDEF2(TK_SByte, ZCC_SBYTE, NAME_sByte);
|
|
TOKENDEF2(TK_Byte, ZCC_BYTE, NAME_Byte);
|
|
TOKENDEF2(TK_Short, ZCC_SHORT, NAME_Short);
|
|
TOKENDEF2(TK_UShort, ZCC_USHORT, NAME_uShort);
|
|
TOKENDEF2(TK_Int8, ZCC_SBYTE, NAME_int8);
|
|
TOKENDEF2(TK_UInt8, ZCC_BYTE, NAME_uint8);
|
|
TOKENDEF2(TK_Int16, ZCC_SHORT, NAME_int16);
|
|
TOKENDEF2(TK_UInt16, ZCC_USHORT, NAME_uint16);
|
|
TOKENDEF2(TK_Int, ZCC_INT, NAME_Int);
|
|
TOKENDEF2(TK_UInt, ZCC_UINT, NAME_uInt);
|
|
TOKENDEF2(TK_Bool, ZCC_BOOL, NAME_Bool);
|
|
TOKENDEF2(TK_Float, ZCC_FLOAT, NAME_Float);
|
|
TOKENDEF2(TK_Double, ZCC_DOUBLE, NAME_Double);
|
|
TOKENDEF2(TK_String, ZCC_STRING, NAME_String);
|
|
TOKENDEF2(TK_Vector2, ZCC_VECTOR2, NAME_Vector2);
|
|
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
|
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
|
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
|
TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator);
|
|
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
|
TOKENDEF2(TK_FunctionType, ZCC_FNTYPE, NAME_Function);
|
|
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
|
TOKENDEF (TK_Void, ZCC_VOID);
|
|
TOKENDEF (TK_True, ZCC_TRUE);
|
|
TOKENDEF (TK_False, ZCC_FALSE);
|
|
TOKENDEF ('[', ZCC_LBRACKET);
|
|
TOKENDEF (']', ZCC_RBRACKET);
|
|
TOKENDEF (TK_In, ZCC_IN);
|
|
TOKENDEF (TK_Out, ZCC_OUT);
|
|
TOKENDEF (TK_Super, ZCC_SUPER);
|
|
TOKENDEF (TK_Null, ZCC_NULLPTR);
|
|
TOKENDEF (TK_Sealed, ZCC_SEALED);
|
|
TOKENDEF ('~', ZCC_TILDE);
|
|
TOKENDEF ('!', ZCC_BANG);
|
|
TOKENDEF (TK_SizeOf, ZCC_SIZEOF);
|
|
TOKENDEF (TK_AlignOf, ZCC_ALIGNOF);
|
|
TOKENDEF (TK_Continue, ZCC_CONTINUE);
|
|
TOKENDEF (TK_Break, ZCC_BREAK);
|
|
TOKENDEF (TK_Return, ZCC_RETURN);
|
|
TOKENDEF (TK_Do, ZCC_DO);
|
|
TOKENDEF (TK_For, ZCC_FOR);
|
|
TOKENDEF (TK_ForEach, ZCC_FOREACH);
|
|
TOKENDEF (TK_While, ZCC_WHILE);
|
|
TOKENDEF (TK_Until, ZCC_UNTIL);
|
|
TOKENDEF (TK_If, ZCC_IF);
|
|
TOKENDEF (TK_Else, ZCC_ELSE);
|
|
TOKENDEF (TK_Switch, ZCC_SWITCH);
|
|
TOKENDEF (TK_Case, ZCC_CASE);
|
|
TOKENDEF2(TK_Default, ZCC_DEFAULT, NAME_Default);
|
|
TOKENDEF (TK_Const, ZCC_CONST);
|
|
TOKENDEF (TK_Stop, ZCC_STOP);
|
|
TOKENDEF (TK_Wait, ZCC_WAIT);
|
|
TOKENDEF (TK_Fail, ZCC_FAIL);
|
|
TOKENDEF (TK_Loop, ZCC_LOOP);
|
|
TOKENDEF (TK_Goto, ZCC_GOTO);
|
|
TOKENDEF (TK_States, ZCC_STATES);
|
|
TOKENDEF2(TK_State, ZCC_STATE, NAME_State);
|
|
TOKENDEF2(TK_Color, ZCC_COLOR, NAME_Color);
|
|
TOKENDEF2(TK_Sound, ZCC_SOUND, NAME_Sound);
|
|
TOKENDEF2(TK_Let, ZCC_LET, NAME_let);
|
|
TOKENDEF2(TK_StaticConst, ZCC_STATICCONST,NAME_Staticconst);
|
|
|
|
TOKENDEF (TK_Identifier, ZCC_IDENTIFIER);
|
|
TOKENDEF (TK_StringConst, ZCC_STRCONST);
|
|
TOKENDEF (TK_NameConst, ZCC_NAMECONST);
|
|
TOKENDEF (TK_IntConst, ZCC_INTCONST);
|
|
TOKENDEF (TK_UIntConst, ZCC_UINTCONST);
|
|
TOKENDEF (TK_FloatConst, ZCC_FLOATCONST);
|
|
TOKENDEF (TK_NonWhitespace, ZCC_NWS);
|
|
|
|
TOKENDEF (TK_Bright, ZCC_BRIGHT);
|
|
TOKENDEF (TK_Slow, ZCC_SLOW);
|
|
TOKENDEF (TK_Fast, ZCC_FAST);
|
|
TOKENDEF (TK_NoDelay, ZCC_NODELAY);
|
|
TOKENDEF (TK_Offset, ZCC_OFFSET);
|
|
TOKENDEF (TK_CanRaise, ZCC_CANRAISE);
|
|
TOKENDEF (TK_Light, ZCC_LIGHT);
|
|
TOKENDEF (TK_Extend, ZCC_EXTEND);
|
|
}
|
|
#undef TOKENDEF
|
|
#undef TOKENDEF2
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
static void ParseSingleFile(FScanner *pSC, const char *filename, int lump, void *parser, ZCCParseState &state)
|
|
{
|
|
int tokentype;
|
|
//bool failed;
|
|
ZCCToken value;
|
|
FScanner lsc;
|
|
|
|
if (pSC == nullptr)
|
|
{
|
|
if (filename != nullptr)
|
|
{
|
|
lump = fileSystem.CheckNumForFullName(filename, true);
|
|
if (lump >= 0)
|
|
{
|
|
lsc.OpenLumpNum(lump);
|
|
}
|
|
else
|
|
{
|
|
Printf("Could not find script lump '%s'\n", filename);
|
|
return;
|
|
}
|
|
}
|
|
else lsc.OpenLumpNum(lump);
|
|
|
|
pSC = &lsc;
|
|
}
|
|
FScanner &sc = *pSC;
|
|
sc.SetParseVersion(state.ParseVersion);
|
|
state.sc = ≻
|
|
|
|
while (sc.GetToken())
|
|
{
|
|
value.Largest = 0;
|
|
value.SourceLoc = sc.GetMessageLine();
|
|
switch (sc.TokenType)
|
|
{
|
|
case TK_StringConst:
|
|
value.String = state.Strings.Alloc(sc.String, sc.StringLen);
|
|
tokentype = ZCC_STRCONST;
|
|
break;
|
|
|
|
case TK_NameConst:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_NAMECONST;
|
|
break;
|
|
|
|
case TK_IntConst:
|
|
value.Int = sc.Number;
|
|
tokentype = ZCC_INTCONST;
|
|
break;
|
|
|
|
case TK_UIntConst:
|
|
value.Int = sc.Number;
|
|
tokentype = ZCC_UINTCONST;
|
|
break;
|
|
|
|
case TK_FloatConst:
|
|
value.Float = sc.Float;
|
|
tokentype = ZCC_FLOATCONST;
|
|
break;
|
|
|
|
case TK_None: // 'NONE' is a token for SBARINFO but not here.
|
|
case TK_Identifier:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_IDENTIFIER;
|
|
break;
|
|
|
|
case TK_NonWhitespace:
|
|
value.Int = FName(sc.String).GetIndex();
|
|
tokentype = ZCC_NWS;
|
|
break;
|
|
|
|
case TK_Static:
|
|
sc.MustGetAnyToken();
|
|
// The oh so wonderful grammar has problems with the 'const' token thanks to the overly broad rule for constants,
|
|
// which effectively prevents use of this token nearly anywhere else. So in order to get 'static const' through
|
|
// on the class/struct level we have to muck around with the token type here so that both words get combined into
|
|
// a single token that doesn't make the grammar throw a fit.
|
|
if (sc.TokenType == TK_Const)
|
|
{
|
|
tokentype = ZCC_STATICCONST;
|
|
value.Int = NAME_Staticconst;
|
|
}
|
|
else
|
|
{
|
|
tokentype = ZCC_STATIC;
|
|
value.Int = NAME_Static;
|
|
sc.UnGet();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
TokenMapEntry *zcctoken = TokenMap.CheckKey(sc.TokenType);
|
|
if (zcctoken != nullptr)
|
|
{
|
|
tokentype = zcctoken->TokenType;
|
|
value.Int = zcctoken->TokenName;
|
|
}
|
|
else
|
|
{
|
|
sc.ScriptMessage("Unexpected token %s.\n", sc.TokenName(sc.TokenType).GetChars());
|
|
goto parse_end;
|
|
}
|
|
break;
|
|
}
|
|
ZCCParse(parser, tokentype, value, &state);
|
|
}
|
|
parse_end:
|
|
value.Int = -1;
|
|
ZCCParse(parser, ZCC_EOF, value, &state);
|
|
state.sc = nullptr;
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|
{
|
|
FScanner sc;
|
|
void *parser;
|
|
ZCCToken value;
|
|
int lumpnum = baselump;
|
|
auto fileno = fileSystem.GetFileContainer(lumpnum);
|
|
|
|
state.FileNo = fileno;
|
|
|
|
if (TokenMap.CountUsed() == 0)
|
|
{
|
|
InitTokenMap();
|
|
}
|
|
|
|
parser = ZCCParseAlloc(malloc);
|
|
|
|
#ifndef NDEBUG
|
|
FILE *f = nullptr;
|
|
const char *tracefile = Args->CheckValue("-tracefile");
|
|
if (tracefile != nullptr)
|
|
{
|
|
f = fopen(tracefile, "w");
|
|
char prompt = '\0';
|
|
ZCCParseTrace(f, &prompt);
|
|
}
|
|
#endif
|
|
|
|
sc.OpenLumpNum(lumpnum);
|
|
sc.SetParseVersion({ 2, 4 }); // To get 'version' we need parse version 2.4 for the initial test
|
|
auto saved = sc.SavePos();
|
|
|
|
if (sc.GetToken())
|
|
{
|
|
if (sc.TokenType == TK_Version)
|
|
{
|
|
char *endp;
|
|
sc.MustGetString();
|
|
state.ParseVersion.major = (int16_t)clamp<unsigned long long>(strtoull(sc.String, &endp, 10), 0, USHRT_MAX);
|
|
if (*endp != '.')
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
state.ParseVersion.minor = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
|
if (*endp == '.')
|
|
{
|
|
state.ParseVersion.revision = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
|
}
|
|
else state.ParseVersion.revision = 0;
|
|
if (*endp != 0)
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
if (state.ParseVersion.major == USHRT_MAX || state.ParseVersion.minor == USHRT_MAX || state.ParseVersion.revision == USHRT_MAX)
|
|
{
|
|
sc.ScriptError("Bad version directive");
|
|
}
|
|
if (state.ParseVersion > MakeVersion(VER_MAJOR, VER_MINOR, VER_REVISION))
|
|
{
|
|
sc.ScriptError("The file you are attempting to run requires a newer version of " GAMENAME ".\n\nA version with ZScript version %d.%d.%d is required, but your copy of " GAMENAME " only supports %d.%d.%d. Please upgrade!", state.ParseVersion.major, state.ParseVersion.minor, state.ParseVersion.revision, VER_MAJOR, VER_MINOR, VER_REVISION);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
state.ParseVersion = MakeVersion(2, 3); // 2.3 is the first version of ZScript.
|
|
sc.RestorePos(saved);
|
|
}
|
|
}
|
|
|
|
ParseSingleFile(&sc, nullptr, lumpnum, parser, state);
|
|
for (unsigned i = 0; i < Includes.Size(); i++)
|
|
{
|
|
lumpnum = fileSystem.CheckNumForFullName(Includes[i].GetChars(), true);
|
|
if (lumpnum == -1)
|
|
{
|
|
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
|
}
|
|
else
|
|
{
|
|
auto fileno2 = fileSystem.GetFileContainer(lumpnum);
|
|
if (fileno == 0 && fileno2 != 0)
|
|
{
|
|
I_FatalError("File %s is overriding core lump %s.",
|
|
fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars());
|
|
}
|
|
|
|
ParseSingleFile(nullptr, nullptr, lumpnum, parser, state);
|
|
}
|
|
}
|
|
Includes.Clear();
|
|
Includes.ShrinkToFit();
|
|
IncludeLocs.Clear();
|
|
IncludeLocs.ShrinkToFit();
|
|
|
|
value.Int = -1;
|
|
value.SourceLoc = sc.GetMessageLine();
|
|
ZCCParse(parser, 0, value, &state);
|
|
ZCCParseFree(parser, free);
|
|
|
|
// If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors.
|
|
if (FScriptPosition::ErrorCounter > 0)
|
|
{
|
|
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).c_str());
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
if (f != nullptr)
|
|
{
|
|
fclose(f);
|
|
}
|
|
#endif
|
|
|
|
// Make a dump of the AST before running the compiler for diagnostic purposes.
|
|
if (Args->CheckParm("-dumpast"))
|
|
{
|
|
FString ast = ZCC_PrintAST(state.TopNode);
|
|
FString filename = fileSystem.GetFileFullPath(baselump).c_str();
|
|
filename.ReplaceChars(":\\/?|", '.');
|
|
filename << ".ast";
|
|
FileWriter *ff = FileWriter::Open(filename.GetChars());
|
|
if (ff != NULL)
|
|
{
|
|
ff->Write(ast.GetChars(), ast.Len());
|
|
delete ff;
|
|
}
|
|
}
|
|
|
|
auto newns = fileSystem.GetFileContainer(baselump) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(fileSystem.GetFileContainer(baselump));
|
|
return newns;
|
|
}
|
|
|
|
static FString ZCCTokenName(int terminal)
|
|
{
|
|
if (terminal == ZCC_EOF)
|
|
{
|
|
return "end of file";
|
|
}
|
|
int sc_token;
|
|
if (terminal > 0 && terminal < (int)countof(BackTokenMap))
|
|
{
|
|
sc_token = BackTokenMap[terminal];
|
|
if (sc_token == 0)
|
|
{ // This token was not initialized. Whoops!
|
|
sc_token = -terminal;
|
|
}
|
|
}
|
|
else
|
|
{ // This should never happen.
|
|
sc_token = -terminal;
|
|
}
|
|
return FScanner::TokenName(sc_token);
|
|
}
|
|
|
|
ZCC_TreeNode *ZCC_AST::InitNode(size_t size, EZCCTreeNodeType type, ZCC_TreeNode *basis)
|
|
{
|
|
ZCC_TreeNode *node = (ZCC_TreeNode *)SyntaxArena.Alloc(size);
|
|
node->SiblingNext = node;
|
|
node->SiblingPrev = node;
|
|
node->NodeType = type;
|
|
if (basis != NULL)
|
|
{
|
|
node->SourceName = basis->SourceName;
|
|
node->SourceLump = basis->SourceLump;
|
|
node->SourceLoc = basis->SourceLoc;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ZCC_TreeNode *ZCCParseState::InitNode(size_t size, EZCCTreeNodeType type)
|
|
{
|
|
ZCC_TreeNode *node = ZCC_AST::InitNode(size, type, NULL);
|
|
node->SourceName = Strings.Alloc(sc->ScriptName);
|
|
node->SourceLump = sc->LumpNum;
|
|
return node;
|
|
}
|
|
|
|
// Appends a sibling to this node's sibling list.
|
|
void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling)
|
|
{
|
|
if (thisnode == nullptr)
|
|
{
|
|
// Some bad syntax can actually get here, so better abort so that the user can see the error which caused this.
|
|
I_FatalError("Internal script compiler error. Execution aborted.");
|
|
}
|
|
if (sibling == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ZCC_TreeNode *&SiblingPrev = thisnode->SiblingPrev;
|
|
ZCC_TreeNode *&SiblingNext = thisnode->SiblingNext;
|
|
|
|
// Check integrity of our sibling list.
|
|
assert(SiblingPrev->SiblingNext == thisnode);
|
|
assert(SiblingNext->SiblingPrev == thisnode);
|
|
|
|
// Check integrity of new sibling list.
|
|
assert(sibling->SiblingPrev->SiblingNext == sibling);
|
|
assert(sibling->SiblingNext->SiblingPrev == sibling);
|
|
|
|
ZCC_TreeNode *siblingend = sibling->SiblingPrev;
|
|
SiblingPrev->SiblingNext = sibling;
|
|
sibling->SiblingPrev = SiblingPrev;
|
|
SiblingPrev = siblingend;
|
|
siblingend->SiblingNext = thisnode;
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
const char *GetMixinTypeString(EZCCMixinType type) {
|
|
switch (type) {
|
|
case ZCC_Mixin_Class:
|
|
return "class";
|
|
|
|
default:
|
|
assert(0 && "Unhandled mixin type");
|
|
return "invalid type";
|
|
}
|
|
}
|
|
|
|
//**--------------------------------------------------------------------------
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList);
|
|
void TreeNodeDeepCopy_Base(ZCC_AST *ast, ZCC_TreeNode *orig, ZCC_TreeNode *copy, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList)
|
|
{
|
|
copy->SourceName = orig->SourceName;
|
|
copy->SourceLump = orig->SourceLump;
|
|
copy->SourceLoc = orig->SourceLoc;
|
|
copy->NodeType = orig->NodeType;
|
|
|
|
if (copySiblings)
|
|
{
|
|
auto node = orig->SiblingNext;
|
|
while (node != orig)
|
|
{
|
|
auto nextNode = TreeNodeDeepCopy_Internal(ast, node, false, copiedNodesList);
|
|
auto newLast = nextNode->SiblingPrev;
|
|
|
|
auto firstNode = copy;
|
|
auto lastNode = firstNode->SiblingPrev;
|
|
|
|
lastNode->SiblingNext = nextNode;
|
|
firstNode->SiblingPrev = newLast;
|
|
|
|
nextNode->SiblingPrev = lastNode;
|
|
newLast->SiblingNext = firstNode;
|
|
|
|
node = node->SiblingNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define GetTreeNode(type) static_cast<ZCC_##type *>(ast->InitNode(sizeof(ZCC_##type), AST_##type, nullptr));
|
|
#define TreeNodeDeepCopy_Start(type) \
|
|
auto copy = GetTreeNode(type); \
|
|
auto origCasted = static_cast<ZCC_##type *>(orig); \
|
|
ret = copy; \
|
|
copiedNodesList->Insert(orig, ret);
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings)
|
|
{
|
|
TMap<ZCC_TreeNode *, ZCC_TreeNode *> copiedNodesList;
|
|
copiedNodesList.Clear();
|
|
|
|
return TreeNodeDeepCopy_Internal(ast, orig, copySiblings, &copiedNodesList);
|
|
}
|
|
|
|
ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings, TMap<ZCC_TreeNode *, ZCC_TreeNode *> *copiedNodesList)
|
|
{
|
|
// [pbeta] This is a legitimate case as otherwise this function would need
|
|
// an excessive amount of "if" statements, so just return null.
|
|
if (orig == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// [pbeta] We need to keep and check a list of already copied nodes, because
|
|
// some are supposed to be the same, and it can cause infinite loops.
|
|
auto existingCopy = copiedNodesList->CheckKey(orig);
|
|
if (existingCopy != nullptr)
|
|
{
|
|
return *existingCopy;
|
|
}
|
|
|
|
ZCC_TreeNode *ret = nullptr;
|
|
|
|
switch (orig->NodeType)
|
|
{
|
|
case AST_Identifier:
|
|
{
|
|
TreeNodeDeepCopy_Start(Identifier);
|
|
|
|
// ZCC_Identifier
|
|
copy->Id = origCasted->Id;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Struct:
|
|
{
|
|
TreeNodeDeepCopy_Start(Struct);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Struct
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->Type = origCasted->Type;
|
|
copy->Version = origCasted->Version;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Class:
|
|
{
|
|
TreeNodeDeepCopy_Start(Class);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Struct
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->Type = origCasted->Type;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_Class
|
|
copy->ParentName = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->ParentName, true, copiedNodesList));
|
|
copy->Replaces = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Replaces, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Enum:
|
|
{
|
|
TreeNodeDeepCopy_Start(Enum);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Enum
|
|
copy->EnumType = origCasted->EnumType;
|
|
copy->Elements = static_cast<ZCC_ConstantDef *>(TreeNodeDeepCopy_Internal(ast, origCasted->Elements, false, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_EnumTerminator:
|
|
{
|
|
TreeNodeDeepCopy_Start (EnumTerminator);
|
|
break;
|
|
}
|
|
|
|
case AST_States:
|
|
{
|
|
TreeNodeDeepCopy_Start(States);
|
|
|
|
// ZCC_States
|
|
copy->Body = static_cast<ZCC_StatePart *>(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList));
|
|
copy->Flags = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Flags, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StatePart:
|
|
{
|
|
TreeNodeDeepCopy_Start (StatePart);
|
|
break;
|
|
}
|
|
|
|
case AST_StateLabel:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateLabel);
|
|
|
|
// ZCC_StateLabel
|
|
copy->Label = origCasted->Label;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StateStop:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateStop);
|
|
break;
|
|
}
|
|
|
|
case AST_StateWait:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateWait);
|
|
break;
|
|
}
|
|
|
|
case AST_StateFail:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateFail);
|
|
break;
|
|
}
|
|
|
|
case AST_StateLoop:
|
|
{
|
|
TreeNodeDeepCopy_Start (StateLoop);
|
|
break;
|
|
}
|
|
|
|
case AST_StateGoto:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateGoto);
|
|
|
|
// ZCC_StateGoto
|
|
copy->Qualifier = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Qualifier, true, copiedNodesList));
|
|
copy->Label = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Label, true, copiedNodesList));
|
|
copy->Offset = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StateLine:
|
|
{
|
|
TreeNodeDeepCopy_Start(StateLine);
|
|
|
|
// ZCC_StateLine
|
|
copy->Sprite = origCasted->Sprite;
|
|
|
|
copy->bBright = origCasted->bBright;
|
|
copy->bFast = origCasted->bFast;
|
|
copy->bSlow = origCasted->bSlow;
|
|
copy->bNoDelay = origCasted->bNoDelay;
|
|
copy->bCanRaise = origCasted->bCanRaise;
|
|
|
|
copy->Frames = origCasted->Frames;
|
|
copy->Duration = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Duration, true, copiedNodesList));
|
|
copy->Offset = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Offset, true, copiedNodesList));
|
|
copy->Lights = static_cast<ZCC_ExprConstant *>(TreeNodeDeepCopy_Internal(ast, origCasted->Lights, true, copiedNodesList));
|
|
copy->Action = TreeNodeDeepCopy_Internal(ast, origCasted->Action, true, copiedNodesList);
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarName:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarName);
|
|
|
|
// ZCC_VarName
|
|
copy->Name = origCasted->Name;
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarInit:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarInit);
|
|
|
|
// ZCC_VarName
|
|
copy->Name = origCasted->Name;
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_VarInit
|
|
copy->Init = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Init, true, copiedNodesList));
|
|
copy->InitIsArray = origCasted->InitIsArray;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Type:
|
|
{
|
|
TreeNodeDeepCopy_Start(Type);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_BasicType:
|
|
{
|
|
TreeNodeDeepCopy_Start(BasicType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_BasicType
|
|
copy->Type = origCasted->Type;
|
|
copy->UserType = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->UserType, true, copiedNodesList));
|
|
copy->isconst = origCasted->isconst;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MapType:
|
|
{
|
|
TreeNodeDeepCopy_Start(MapType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_MapType
|
|
copy->KeyType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList));
|
|
copy->ValueType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MapIteratorType:
|
|
{
|
|
TreeNodeDeepCopy_Start(MapIteratorType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// AST_MapIteratorType
|
|
copy->KeyType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList));
|
|
copy->ValueType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_DynArrayType:
|
|
{
|
|
TreeNodeDeepCopy_Start(DynArrayType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_DynArrayType
|
|
copy->ElementType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ElementType, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncPtrParamDecl:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncPtrParamDecl);
|
|
|
|
// ZCC_FuncPtrParamDecl
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncPtrType:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncPtrType);
|
|
|
|
// ZCC_FuncPtrType
|
|
copy->RetType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->RetType, true, copiedNodesList));
|
|
copy->Params = static_cast<ZCC_FuncPtrParamDecl *>(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList));
|
|
copy->Scope = origCasted->Scope;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ClassType:
|
|
{
|
|
TreeNodeDeepCopy_Start(ClassType);
|
|
|
|
// ZCC_Type
|
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
|
// ZCC_ClassType
|
|
copy->Restriction = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Restriction, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Expression:
|
|
{
|
|
TreeNodeDeepCopy_Start(Expression);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprID:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprID);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprID
|
|
copy->Identifier = origCasted->Identifier;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprTypeRef:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprTypeRef);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprTypeRef
|
|
copy->RefType = origCasted->RefType;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprConstant:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprConstant);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprConstant
|
|
// Currently handled: StringVal, IntVal and DoubleVal. (UIntVal appears to be completely unused.)
|
|
if (origCasted->Type == TypeString)
|
|
{
|
|
copy->StringVal = origCasted->StringVal;
|
|
}
|
|
else if (origCasted->Type == TypeFloat64 || origCasted->Type == TypeFloat32)
|
|
{
|
|
copy->DoubleVal = origCasted->DoubleVal;
|
|
}
|
|
else if (origCasted->Type == TypeName || origCasted->Type->isIntCompatible())
|
|
{
|
|
copy->IntVal = origCasted->IntVal;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprFuncCall:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprFuncCall);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprFuncCall
|
|
copy->Function = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Function, true, copiedNodesList));
|
|
copy->Parameters = static_cast<ZCC_FuncParm *>(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprMemberAccess:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprMemberAccess);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprMemberAccess
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = origCasted->Right;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprUnary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprUnary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprUnary
|
|
copy->Operand = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Operand, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprBinary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprBinary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprBinary
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExprTrinary:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExprTrinary);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ExprTrinary
|
|
copy->Test = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Test, true, copiedNodesList));
|
|
copy->Left = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Left, true, copiedNodesList));
|
|
copy->Right = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Right, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncParm:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncParm);
|
|
|
|
// ZCC_FuncParm
|
|
copy->Value = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList));
|
|
copy->Label = origCasted->Label;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Statement:
|
|
{
|
|
TreeNodeDeepCopy_Start (Statement);
|
|
break;
|
|
}
|
|
|
|
case AST_CompoundStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(CompoundStmt);
|
|
|
|
// ZCC_CompoundStmt
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ContinueStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start (ContinueStmt);
|
|
break;
|
|
}
|
|
|
|
case AST_BreakStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start (BreakStmt);
|
|
break;
|
|
}
|
|
|
|
case AST_ReturnStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(ReturnStmt);
|
|
|
|
// ZCC_ReturnStmt
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ExpressionStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(ExpressionStmt);
|
|
|
|
// ZCC_ExpressionStmt
|
|
copy->Expression = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Expression, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_IterationStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(IterationStmt);
|
|
|
|
// ZCC_IterationStmt
|
|
copy->LoopCondition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopCondition, true, copiedNodesList));
|
|
copy->LoopStatement = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList));
|
|
copy->LoopBumper = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopBumper, true, copiedNodesList));
|
|
copy->CheckAt = origCasted->CheckAt;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ArrayIterationStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(ArrayIterationStmt);
|
|
|
|
// ZCC_ArrayIterationStmt
|
|
copy->ItName = static_cast<ZCC_VarName*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItName, true, copiedNodesList));
|
|
copy->LoopStatement = static_cast<ZCC_Statement*>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList));
|
|
copy->ItArray = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItArray, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_IfStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(IfStmt);
|
|
|
|
// ZCC_IfStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
copy->TruePath = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->TruePath, true, copiedNodesList));
|
|
copy->FalsePath = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->FalsePath, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_SwitchStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(SwitchStmt);
|
|
|
|
// ZCC_SwitchStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_CaseStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(CaseStmt);
|
|
|
|
// ZCC_CaseStmt
|
|
copy->Condition = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Condition, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_AssignStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(AssignStmt);
|
|
|
|
// ZCC_AssignStmt
|
|
copy->Dests = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Dests, true, copiedNodesList));
|
|
copy->Sources = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Sources, true, copiedNodesList));
|
|
copy->AssignOp = origCasted->AssignOp;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_AssignDeclStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(AssignDeclStmt);
|
|
|
|
// ZCC_AssignDeclStmt
|
|
copy->Dests = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Dests, true, copiedNodesList));
|
|
copy->Sources = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Sources, true, copiedNodesList));
|
|
copy->AssignOp = origCasted->AssignOp;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_LocalVarStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(LocalVarStmt);
|
|
|
|
// ZCC_LocalVarStmt
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Vars = static_cast<ZCC_VarInit *>(TreeNodeDeepCopy_Internal(ast, origCasted->Vars, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncParamDecl:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncParamDecl);
|
|
|
|
// ZCC_FuncParamDecl
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Default = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Default, true, copiedNodesList));
|
|
copy->Name = origCasted->Name;
|
|
copy->Flags = origCasted->Flags;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ConstantDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(ConstantDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_ConstantDef
|
|
copy->Value = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Value, true, copiedNodesList));
|
|
copy->Symbol = origCasted->Symbol;
|
|
if (copy->Symbol != nullptr)
|
|
{
|
|
copy->Type = static_cast<ZCC_Enum *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Declarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(Declarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VarDeclarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(VarDeclarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_VarDeclarator
|
|
copy->Names = static_cast<ZCC_VarName *>(TreeNodeDeepCopy_Internal(ast, origCasted->Names, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FuncDeclarator:
|
|
{
|
|
TreeNodeDeepCopy_Start(FuncDeclarator);
|
|
|
|
// ZCC_Declarator
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Flags = origCasted->Flags;
|
|
copy->Version = origCasted->Version;
|
|
// ZCC_FuncDeclarator
|
|
copy->Params = static_cast<ZCC_FuncParamDecl *>(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList));
|
|
copy->Name = origCasted->Name;
|
|
copy->Body = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList));
|
|
copy->UseFlags = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->UseFlags, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Default:
|
|
{
|
|
TreeNodeDeepCopy_Start(Default);
|
|
|
|
// ZCC_CompoundStmt
|
|
copy->Content = static_cast<ZCC_Statement *>(TreeNodeDeepCopy_Internal(ast, origCasted->Content, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FlagStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(FlagStmt);
|
|
|
|
// ZCC_FlagStmt
|
|
copy->name = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->name, true, copiedNodesList));
|
|
copy->set = origCasted->set;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_PropertyStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(PropertyStmt);
|
|
|
|
// ZCC_PropertyStmt
|
|
copy->Prop = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Prop, true, copiedNodesList));
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_VectorValue:
|
|
{
|
|
TreeNodeDeepCopy_Start(VectorValue);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_VectorValue
|
|
copy->X = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->X, true, copiedNodesList));
|
|
copy->Y = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Y, true, copiedNodesList));
|
|
copy->Z = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->Z, true, copiedNodesList));
|
|
copy->W = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->W, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_DeclFlags:
|
|
{
|
|
TreeNodeDeepCopy_Start(DeclFlags);
|
|
|
|
// ZCC_DeclFlags
|
|
copy->Id = static_cast<ZCC_Identifier *>(TreeNodeDeepCopy_Internal(ast, origCasted->Id, true, copiedNodesList));
|
|
copy->DeprecationMessage = origCasted->DeprecationMessage;
|
|
copy->Version = origCasted->Version;
|
|
copy->Flags = origCasted->Flags;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_ClassCast:
|
|
{
|
|
TreeNodeDeepCopy_Start(ClassCast);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_ClassCast
|
|
copy->ClassName = origCasted->ClassName;
|
|
copy->Parameters = static_cast<ZCC_FuncParm *>(TreeNodeDeepCopy_Internal(ast, origCasted->Parameters, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FunctionPtrCast:
|
|
{
|
|
TreeNodeDeepCopy_Start(FunctionPtrCast);
|
|
|
|
// ZCC_Expression
|
|
copy->Operation = origCasted->Operation;
|
|
copy->Type = origCasted->Type;
|
|
// ZCC_FunctionPtrCast
|
|
copy->PtrType = static_cast<ZCC_FuncPtrType *>(TreeNodeDeepCopy_Internal(ast, origCasted->PtrType, true, copiedNodesList));
|
|
copy->Expr = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Expr, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_StaticArrayStatement:
|
|
{
|
|
TreeNodeDeepCopy_Start(StaticArrayStatement);
|
|
|
|
// ZCC_StaticArrayStatement
|
|
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
|
copy->Id = origCasted->Id;
|
|
copy->Values = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Values, true, copiedNodesList));
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_Property:
|
|
{
|
|
TreeNodeDeepCopy_Start(Property);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_Property
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_FlagDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(FlagDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_FlagDef
|
|
copy->RefName = origCasted->RefName;
|
|
copy->BitValue = origCasted->BitValue;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MixinDef:
|
|
{
|
|
TreeNodeDeepCopy_Start(MixinDef);
|
|
|
|
// ZCC_NamedNode
|
|
copy->NodeName = origCasted->NodeName;
|
|
copy->Symbol = origCasted->Symbol;
|
|
// ZCC_MixinDef
|
|
copy->Body = TreeNodeDeepCopy_Internal(ast, origCasted->Body, true, copiedNodesList);
|
|
copy->MixinType = origCasted->MixinType;
|
|
|
|
break;
|
|
}
|
|
|
|
case AST_MixinStmt:
|
|
{
|
|
TreeNodeDeepCopy_Start(MixinStmt);
|
|
|
|
// ZCC_MixinStmt
|
|
copy->MixinName = origCasted->MixinName;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
assert(0 && "Unimplemented node type");
|
|
break;
|
|
}
|
|
|
|
TreeNodeDeepCopy_Base(ast, orig, ret, copySiblings, copiedNodesList);
|
|
|
|
return ret;
|
|
} |