mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-20 20:16:40 +00:00
- added the script compiler's front end.
This commit is contained in:
parent
99d3dc67ae
commit
006916a0a6
14 changed files with 15971 additions and 1 deletions
982
source/common/scripting/frontend/ast.cpp
Normal file
982
source/common/scripting/frontend/ast.cpp
Normal file
|
@ -0,0 +1,982 @@
|
|||
/*
|
||||
** ast.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 "vmintern.h"
|
||||
#include "types.h"
|
||||
#include "zcc_parser.h"
|
||||
#include "zcc-parse.h"
|
||||
#include "printf.h"
|
||||
|
||||
class FLispString;
|
||||
extern void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *);
|
||||
|
||||
static const char *BuiltInTypeNames[] =
|
||||
{
|
||||
"sint8", "uint8",
|
||||
"sint16", "uint16",
|
||||
"sint32", "uint32_t",
|
||||
"intauto",
|
||||
|
||||
"bool",
|
||||
"float64", "floatauto",
|
||||
"string",
|
||||
"vector2",
|
||||
"vector3",
|
||||
"name",
|
||||
|
||||
"color",
|
||||
"state",
|
||||
"sound",
|
||||
|
||||
"usertype",
|
||||
"nativetype",
|
||||
"let",
|
||||
};
|
||||
|
||||
class FLispString
|
||||
{
|
||||
public:
|
||||
operator FString &() { return Str; }
|
||||
|
||||
FLispString()
|
||||
{
|
||||
NestDepth = Column = 0;
|
||||
WrapWidth = 200;
|
||||
NeedSpace = false;
|
||||
ConsecOpens = 0;
|
||||
}
|
||||
|
||||
void Open(const char *label)
|
||||
{
|
||||
size_t labellen = label != NULL ? strlen(label) : 0;
|
||||
CheckWrap(labellen + 1 + NeedSpace);
|
||||
if (NeedSpace)
|
||||
{
|
||||
Str << ' ';
|
||||
ConsecOpens = 0;
|
||||
}
|
||||
Str << '(';
|
||||
ConsecOpens++;
|
||||
if (label != NULL)
|
||||
{
|
||||
Str.AppendCStrPart(label, labellen);
|
||||
}
|
||||
Column += labellen + 1 + NeedSpace;
|
||||
NestDepth++;
|
||||
NeedSpace = (label != NULL);
|
||||
}
|
||||
void Close()
|
||||
{
|
||||
assert(NestDepth != 0);
|
||||
Str << ')';
|
||||
Column++;
|
||||
NestDepth--;
|
||||
NeedSpace = true;
|
||||
}
|
||||
void Break()
|
||||
{
|
||||
// Don't break if not needed.
|
||||
if (Column != NestDepth)
|
||||
{
|
||||
if (NeedSpace)
|
||||
{
|
||||
ConsecOpens = 0;
|
||||
}
|
||||
else
|
||||
{ // Move hanging ( characters to the new line
|
||||
Str.Truncate(Str.Len() - ConsecOpens);
|
||||
NestDepth -= ConsecOpens;
|
||||
}
|
||||
Str << '\n';
|
||||
Column = NestDepth;
|
||||
NeedSpace = false;
|
||||
if (NestDepth > 0)
|
||||
{
|
||||
Str.AppendFormat("%*s", (int)NestDepth, "");
|
||||
}
|
||||
if (ConsecOpens > 0)
|
||||
{
|
||||
for (size_t i = 0; i < ConsecOpens; ++i)
|
||||
{
|
||||
Str << '(';
|
||||
}
|
||||
NestDepth += ConsecOpens;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool CheckWrap(size_t len)
|
||||
{
|
||||
if (len + Column > WrapWidth)
|
||||
{
|
||||
Break();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Add(const char *str, size_t len)
|
||||
{
|
||||
CheckWrap(len + NeedSpace);
|
||||
if (NeedSpace)
|
||||
{
|
||||
Str << ' ';
|
||||
}
|
||||
Str.AppendCStrPart(str, len);
|
||||
Column += len + NeedSpace;
|
||||
NeedSpace = true;
|
||||
}
|
||||
void Add(const char *str)
|
||||
{
|
||||
Add(str, strlen(str));
|
||||
}
|
||||
void Add(FString &str)
|
||||
{
|
||||
Add(str.GetChars(), str.Len());
|
||||
}
|
||||
void AddName(FName name)
|
||||
{
|
||||
size_t namelen = strlen(name.GetChars());
|
||||
CheckWrap(namelen + 2 + NeedSpace);
|
||||
if (NeedSpace)
|
||||
{
|
||||
NeedSpace = false;
|
||||
Str << ' ';
|
||||
}
|
||||
Str << '\'' << name.GetChars() << '\'';
|
||||
Column += namelen + 2 + NeedSpace;
|
||||
NeedSpace = true;
|
||||
}
|
||||
void AddChar(char c)
|
||||
{
|
||||
Add(&c, 1);
|
||||
}
|
||||
void AddInt(int i, bool un=false)
|
||||
{
|
||||
char buf[16];
|
||||
size_t len;
|
||||
if (!un)
|
||||
{
|
||||
len = mysnprintf(buf, countof(buf), "%d", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = mysnprintf(buf, countof(buf), "%uu", i);
|
||||
}
|
||||
Add(buf, len);
|
||||
}
|
||||
void AddHex(unsigned x)
|
||||
{
|
||||
char buf[10];
|
||||
size_t len = mysnprintf(buf, countof(buf), "%08x", x);
|
||||
Add(buf, len);
|
||||
}
|
||||
void AddFloat(double f, bool single)
|
||||
{
|
||||
char buf[32];
|
||||
size_t len = mysnprintf(buf, countof(buf), "%.4f", f);
|
||||
if (single)
|
||||
{
|
||||
buf[len++] = 'f';
|
||||
buf[len] = '\0';
|
||||
}
|
||||
Add(buf, len);
|
||||
}
|
||||
private:
|
||||
FString Str;
|
||||
size_t NestDepth;
|
||||
size_t Column;
|
||||
size_t WrapWidth;
|
||||
size_t ConsecOpens;
|
||||
bool NeedSpace;
|
||||
};
|
||||
|
||||
static void PrintNode(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
assert(TreeNodePrinter[NUM_AST_NODE_TYPES-1] != NULL);
|
||||
if (node->NodeType >= 0 && node->NodeType < NUM_AST_NODE_TYPES)
|
||||
{
|
||||
TreeNodePrinter[node->NodeType](out, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Open("unknown-node-type");
|
||||
out.AddInt(node->NodeType);
|
||||
out.Close();
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true, bool addbreaks=false)
|
||||
{
|
||||
ZCC_TreeNode *p;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
out.Add("nil", 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newlist)
|
||||
{
|
||||
out.Open(NULL);
|
||||
}
|
||||
p = node;
|
||||
do
|
||||
{
|
||||
if (addbreaks)
|
||||
{
|
||||
out.Break();
|
||||
}
|
||||
PrintNode(out, p);
|
||||
p = p->SiblingNext;
|
||||
} while (p != node);
|
||||
if (newlist)
|
||||
{
|
||||
out.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type)
|
||||
{
|
||||
assert(ZCC_NUM_BUILT_IN_TYPES == countof(BuiltInTypeNames));
|
||||
if (unsigned(type) >= unsigned(ZCC_NUM_BUILT_IN_TYPES))
|
||||
{
|
||||
char buf[30];
|
||||
size_t len = mysnprintf(buf, countof(buf), "bad-type-%u", type);
|
||||
out.Add(buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Add(BuiltInTypeNames[type]);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintIdentifier(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Identifier *inode = (ZCC_Identifier *)node;
|
||||
out.Open("identifier");
|
||||
out.AddName(inode->Id);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStringConst(FLispString &out, FString str)
|
||||
{
|
||||
FString outstr;
|
||||
outstr << '"';
|
||||
for (size_t i = 0; i < str.Len(); ++i)
|
||||
{
|
||||
if (str[i] == '"')
|
||||
{
|
||||
outstr << "\"";
|
||||
}
|
||||
else if (str[i] == '\\')
|
||||
{
|
||||
outstr << "\\\\";
|
||||
}
|
||||
else if (str[i] >= 32)
|
||||
{
|
||||
outstr << str[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
outstr.AppendFormat("\\x%02X", str[i]);
|
||||
}
|
||||
}
|
||||
outstr << '"';
|
||||
out.Add(outstr);
|
||||
}
|
||||
|
||||
static void PrintClass(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Class *cnode = (ZCC_Class *)node;
|
||||
out.Break();
|
||||
out.Open("class");
|
||||
out.AddName(cnode->NodeName);
|
||||
PrintNodes(out, cnode->ParentName);
|
||||
PrintNodes(out, cnode->Replaces);
|
||||
out.AddHex(cnode->Flags);
|
||||
PrintNodes(out, cnode->Body, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStruct(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Struct *snode = (ZCC_Struct *)node;
|
||||
out.Break();
|
||||
out.Open("struct");
|
||||
out.AddName(snode->NodeName);
|
||||
PrintNodes(out, snode->Body, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintProperty(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Property *snode = (ZCC_Property *)node;
|
||||
out.Break();
|
||||
out.Open("property");
|
||||
out.AddName(snode->NodeName);
|
||||
PrintNodes(out, snode->Body, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FlagDef *snode = (ZCC_FlagDef *)node;
|
||||
out.Break();
|
||||
out.Open("flagdef");
|
||||
out.AddName(snode->NodeName);
|
||||
out.AddName(snode->RefName);
|
||||
out.AddInt(snode->BitValue);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
auto *snode = (ZCC_StaticArrayStatement *)node;
|
||||
out.Break();
|
||||
out.Open("static-array");
|
||||
out.AddName(snode->Id);
|
||||
PrintNodes(out, snode->Values, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Enum *enode = (ZCC_Enum *)node;
|
||||
out.Break();
|
||||
out.Open("enum");
|
||||
out.AddName(enode->NodeName);
|
||||
PrintBuiltInType(out, enode->EnumType);
|
||||
out.Add(enode->Elements == NULL ? "nil" : "...", 3);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintEnumTerminator(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("enum-term");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStates(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_States *snode = (ZCC_States *)node;
|
||||
out.Break();
|
||||
out.Open("states");
|
||||
PrintNodes(out, snode->Flags, false, true);
|
||||
PrintNodes(out, snode->Body, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStatePart(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("state-part");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_StateLabel *snode = (ZCC_StateLabel *)node;
|
||||
out.Open("state-label");
|
||||
out.AddName(snode->Label);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateStop(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("state-stop");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateWait(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("state-wait");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateFail(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("state-fail");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateLoop(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("state-loop");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_StateGoto *snode = (ZCC_StateGoto *)node;
|
||||
out.Open("state-goto");
|
||||
PrintNodes(out, snode->Qualifier);
|
||||
PrintNodes(out, snode->Label);
|
||||
PrintNodes(out, snode->Offset);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStateLine(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_StateLine *snode = (ZCC_StateLine *)node;
|
||||
out.Open("state-line");
|
||||
out.Add(*(snode->Sprite));
|
||||
PrintNodes(out, snode->Duration);
|
||||
if (snode->bNoDelay) out.Add("nodelay", 7);
|
||||
if (snode->bBright) out.Add("bright", 6);
|
||||
if (snode->bFast) out.Add("fast", 4);
|
||||
if (snode->bSlow) out.Add("slow", 4);
|
||||
if (snode->bCanRaise) out.Add("canraise", 8);
|
||||
out.Add(*(snode->Frames));
|
||||
PrintNodes(out, snode->Offset);
|
||||
PrintNodes(out, snode->Action, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintVarName(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_VarName *vnode = (ZCC_VarName *)node;
|
||||
out.Open("var-name");
|
||||
PrintNodes(out, vnode->ArraySize);
|
||||
out.AddName(vnode->Name);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintVarInit(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_VarInit *vnode = (ZCC_VarInit *)node;
|
||||
out.Open("var-init");
|
||||
PrintNodes(out, vnode->ArraySize);
|
||||
PrintNodes(out, vnode->Init);
|
||||
if (vnode->InitIsArray) out.Add("array", 5);
|
||||
out.AddName(vnode->Name);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintType(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Type *tnode = (ZCC_Type *)node;
|
||||
out.Open("bad-type");
|
||||
PrintNodes(out, tnode->ArraySize);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintBasicType(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_BasicType *tnode = (ZCC_BasicType *)node;
|
||||
out.Open("basic-type");
|
||||
PrintNodes(out, tnode->ArraySize);
|
||||
PrintBuiltInType(out, tnode->Type);
|
||||
if (tnode->Type == ZCC_UserType || tnode->Type == ZCC_NativeType)
|
||||
{
|
||||
if (tnode->Type == ZCC_NativeType) out.Add("@", 1);
|
||||
PrintNodes(out, tnode->UserType, false);
|
||||
}
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintMapType(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_MapType *tnode = (ZCC_MapType *)node;
|
||||
out.Open("map-type");
|
||||
PrintNodes(out, tnode->ArraySize);
|
||||
PrintNodes(out, tnode->KeyType);
|
||||
PrintNodes(out, tnode->ValueType);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node;
|
||||
out.Open("dyn-array-type");
|
||||
PrintNodes(out, tnode->ArraySize);
|
||||
PrintNodes(out, tnode->ElementType);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintClassType(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ClassType *tnode = (ZCC_ClassType *)node;
|
||||
out.Open("class-type");
|
||||
PrintNodes(out, tnode->ArraySize);
|
||||
PrintNodes(out, tnode->Restriction);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void OpenExprType(FLispString &out, EZCCExprType type)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
if (unsigned(type) < PEX_COUNT_OF)
|
||||
{
|
||||
mysnprintf(buf, countof(buf), "expr %d", type);
|
||||
}
|
||||
else
|
||||
{
|
||||
mysnprintf(buf, countof(buf), "bad-pex-%u", type);
|
||||
}
|
||||
out.Open(buf);
|
||||
}
|
||||
|
||||
static void PrintExpression(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Expression *enode = (ZCC_Expression *)node;
|
||||
OpenExprType(out, enode->Operation);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprID(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprID *enode = (ZCC_ExprID *)node;
|
||||
assert(enode->Operation == PEX_ID);
|
||||
out.Open("expr-id");
|
||||
out.AddName(enode->Identifier);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprTypeRef *enode = (ZCC_ExprTypeRef *)node;
|
||||
assert(enode->Operation == PEX_TypeRef);
|
||||
out.Open("expr-type-ref");
|
||||
if (enode->RefType == TypeSInt8) { out.Add("sint8"); }
|
||||
else if (enode->RefType == TypeUInt8) { out.Add("uint8"); }
|
||||
else if (enode->RefType == TypeSInt16) { out.Add("sint16"); }
|
||||
else if (enode->RefType == TypeSInt32) { out.Add("sint32"); }
|
||||
else if (enode->RefType == TypeFloat32) { out.Add("float32"); }
|
||||
else if (enode->RefType == TypeFloat64) { out.Add("float64"); }
|
||||
else if (enode->RefType == TypeString) { out.Add("string"); }
|
||||
else if (enode->RefType == TypeName) { out.Add("name"); }
|
||||
else if (enode->RefType == TypeColor) { out.Add("color"); }
|
||||
else if (enode->RefType == TypeSound) { out.Add("sound"); }
|
||||
else { out.Add("other"); }
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprConstant *enode = (ZCC_ExprConstant *)node;
|
||||
assert(enode->Operation == PEX_ConstValue);
|
||||
out.Open("expr-const");
|
||||
if (enode->Type == TypeString)
|
||||
{
|
||||
PrintStringConst(out, *enode->StringVal);
|
||||
}
|
||||
else if (enode->Type == TypeFloat64)
|
||||
{
|
||||
out.AddFloat(enode->DoubleVal, false);
|
||||
}
|
||||
else if (enode->Type == TypeFloat32)
|
||||
{
|
||||
out.AddFloat(enode->DoubleVal, true);
|
||||
}
|
||||
else if (enode->Type == TypeName)
|
||||
{
|
||||
out.AddName(ENamedName(enode->IntVal));
|
||||
}
|
||||
else if (enode->Type->isIntCompatible())
|
||||
{
|
||||
out.AddInt(enode->IntVal, static_cast<PInt *>(enode->Type)->Unsigned);
|
||||
}
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprFuncCall *enode = (ZCC_ExprFuncCall *)node;
|
||||
assert(enode->Operation == PEX_FuncCall);
|
||||
out.Open("expr-func-call");
|
||||
PrintNodes(out, enode->Function);
|
||||
PrintNodes(out, enode->Parameters, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ClassCast *enode = (ZCC_ClassCast *)node;
|
||||
assert(enode->Operation == PEX_ClassCast);
|
||||
out.Open("expr-class-cast");
|
||||
out.AddName(enode->ClassName);
|
||||
PrintNodes(out, enode->Parameters, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node;
|
||||
out.Open("static-array-stmt");
|
||||
PrintNodes(out, enode->Type, false);
|
||||
out.AddName(enode->Id);
|
||||
PrintNodes(out, enode->Values, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
||||
assert(enode->Operation == PEX_MemberAccess);
|
||||
out.Open("expr-member-access");
|
||||
PrintNodes(out, enode->Left);
|
||||
out.AddName(enode->Right);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprUnary *enode = (ZCC_ExprUnary *)node;
|
||||
OpenExprType(out, enode->Operation);
|
||||
PrintNodes(out, enode->Operand, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprBinary *enode = (ZCC_ExprBinary *)node;
|
||||
OpenExprType(out, enode->Operation);
|
||||
PrintNodes(out, enode->Left);
|
||||
PrintNodes(out, enode->Right);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprTrinary *enode = (ZCC_ExprTrinary *)node;
|
||||
OpenExprType(out, enode->Operation);
|
||||
PrintNodes(out, enode->Test);
|
||||
PrintNodes(out, enode->Left);
|
||||
PrintNodes(out, enode->Right);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_VectorValue *enode = (ZCC_VectorValue *)node;
|
||||
OpenExprType(out, enode->Operation);
|
||||
PrintNodes(out, enode->X);
|
||||
PrintNodes(out, enode->Y);
|
||||
PrintNodes(out, enode->Z);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FuncParm *pnode = (ZCC_FuncParm *)node;
|
||||
out.Break();
|
||||
out.Open("func-parm");
|
||||
out.AddName(pnode->Label);
|
||||
PrintNodes(out, pnode->Value, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStatement(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Open("statement");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_CompoundStmt *snode = (ZCC_CompoundStmt *)node;
|
||||
out.Break();
|
||||
out.Open("compound-stmt");
|
||||
PrintNodes(out, snode->Content, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintDefault(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Default *snode = (ZCC_Default *)node;
|
||||
out.Break();
|
||||
out.Open("default");
|
||||
PrintNodes(out, snode->Content, false, true);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintContinueStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Break();
|
||||
out.Open("continue-stmt");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintBreakStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
out.Break();
|
||||
out.Open("break-stmt");
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ReturnStmt *snode = (ZCC_ReturnStmt *)node;
|
||||
out.Break();
|
||||
out.Open("return-stmt");
|
||||
PrintNodes(out, snode->Values, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExpressionStmt *snode = (ZCC_ExpressionStmt *)node;
|
||||
out.Break();
|
||||
out.Open("expression-stmt");
|
||||
PrintNodes(out, snode->Expression, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_IterationStmt *snode = (ZCC_IterationStmt *)node;
|
||||
out.Break();
|
||||
out.Open("iteration-stmt");
|
||||
out.Add((snode->CheckAt == ZCC_IterationStmt::Start) ? "start" : "end");
|
||||
out.Break();
|
||||
PrintNodes(out, snode->LoopCondition);
|
||||
out.Break();
|
||||
PrintNodes(out, snode->LoopBumper);
|
||||
out.Break();
|
||||
PrintNodes(out, snode->LoopStatement);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_IfStmt *snode = (ZCC_IfStmt *)node;
|
||||
out.Break();
|
||||
out.Open("if-stmt");
|
||||
PrintNodes(out, snode->Condition);
|
||||
out.Break();
|
||||
PrintNodes(out, snode->TruePath);
|
||||
out.Break();
|
||||
PrintNodes(out, snode->FalsePath);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_SwitchStmt *snode = (ZCC_SwitchStmt *)node;
|
||||
out.Break();
|
||||
out.Open("switch-stmt");
|
||||
PrintNodes(out, snode->Condition);
|
||||
out.Break();
|
||||
PrintNodes(out, snode->Content, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintCaseStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_CaseStmt *snode = (ZCC_CaseStmt *)node;
|
||||
out.Break();
|
||||
out.Open("case-stmt");
|
||||
PrintNodes(out, snode->Condition, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void BadAssignOp(FLispString &out, int op)
|
||||
{
|
||||
char buf[32];
|
||||
size_t len = mysnprintf(buf, countof(buf), "assign-op-%d", op);
|
||||
out.Add(buf, len);
|
||||
}
|
||||
|
||||
static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node;
|
||||
out.Open("assign-stmt");
|
||||
PrintNodes(out, snode->Dests);
|
||||
PrintNodes(out, snode->Sources);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_LocalVarStmt *snode = (ZCC_LocalVarStmt *)node;
|
||||
out.Open("local-var-stmt");
|
||||
PrintNodes(out, snode->Type);
|
||||
PrintNodes(out, snode->Vars);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FuncParamDecl *dnode = (ZCC_FuncParamDecl *)node;
|
||||
out.Break();
|
||||
out.Open("func-param-decl");
|
||||
PrintNodes(out, dnode->Type);
|
||||
out.AddName(dnode->Name);
|
||||
out.AddHex(dnode->Flags);
|
||||
PrintNodes(out, dnode->Default);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ConstantDef *dnode = (ZCC_ConstantDef *)node;
|
||||
out.Break();
|
||||
out.Open("constant-def");
|
||||
out.AddName(dnode->NodeName);
|
||||
PrintNodes(out, dnode->Value, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_Declarator *dnode = (ZCC_Declarator *)node;
|
||||
out.Break();
|
||||
out.Open("declarator");
|
||||
out.AddHex(dnode->Flags);
|
||||
PrintNodes(out, dnode->Type);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_VarDeclarator *dnode = (ZCC_VarDeclarator *)node;
|
||||
out.Break();
|
||||
out.Open("var-declarator");
|
||||
out.AddHex(dnode->Flags);
|
||||
PrintNodes(out, dnode->Type);
|
||||
PrintNodes(out, dnode->Names);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FuncDeclarator *dnode = (ZCC_FuncDeclarator *)node;
|
||||
out.Break();
|
||||
out.Open("func-declarator");
|
||||
out.AddHex(dnode->Flags);
|
||||
PrintNodes(out, dnode->UseFlags);
|
||||
PrintNodes(out, dnode->Type);
|
||||
out.AddName(dnode->Name);
|
||||
PrintNodes(out, dnode->Params);
|
||||
PrintNodes(out, dnode->Body, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
auto dnode = (ZCC_DeclFlags *)node;
|
||||
out.Break();
|
||||
out.Open("decl-flags");
|
||||
out.AddHex(dnode->Flags);
|
||||
PrintNodes(out, dnode->Id);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
auto dnode = (ZCC_FlagStmt *)node;
|
||||
out.Break();
|
||||
out.Open("flag-stmt");
|
||||
PrintNodes(out, dnode->name, false);
|
||||
out.AddInt(dnode->set);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
auto dnode = (ZCC_PropertyStmt *)node;
|
||||
out.Break();
|
||||
out.Open("property-stmt");
|
||||
PrintNodes(out, dnode->Prop, false);
|
||||
PrintNodes(out, dnode->Values, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *) =
|
||||
{
|
||||
PrintIdentifier,
|
||||
PrintClass,
|
||||
PrintStruct,
|
||||
PrintEnum,
|
||||
PrintEnumTerminator,
|
||||
PrintStates,
|
||||
PrintStatePart,
|
||||
PrintStateLabel,
|
||||
PrintStateStop,
|
||||
PrintStateWait,
|
||||
PrintStateFail,
|
||||
PrintStateLoop,
|
||||
PrintStateGoto,
|
||||
PrintStateLine,
|
||||
PrintVarName,
|
||||
PrintVarInit,
|
||||
PrintType,
|
||||
PrintBasicType,
|
||||
PrintMapType,
|
||||
PrintDynArrayType,
|
||||
PrintClassType,
|
||||
PrintExpression,
|
||||
PrintExprID,
|
||||
PrintExprTypeRef,
|
||||
PrintExprConstant,
|
||||
PrintExprFuncCall,
|
||||
PrintExprMemberAccess,
|
||||
PrintExprUnary,
|
||||
PrintExprBinary,
|
||||
PrintExprTrinary,
|
||||
PrintFuncParam,
|
||||
PrintStatement,
|
||||
PrintCompoundStmt,
|
||||
PrintContinueStmt,
|
||||
PrintBreakStmt,
|
||||
PrintReturnStmt,
|
||||
PrintExpressionStmt,
|
||||
PrintIterationStmt,
|
||||
PrintIfStmt,
|
||||
PrintSwitchStmt,
|
||||
PrintCaseStmt,
|
||||
PrintAssignStmt,
|
||||
PrintLocalVarStmt,
|
||||
PrintFuncParamDecl,
|
||||
PrintConstantDef,
|
||||
PrintDeclarator,
|
||||
PrintVarDeclarator,
|
||||
PrintFuncDeclarator,
|
||||
PrintDefault,
|
||||
PrintFlagStmt,
|
||||
PrintPropertyStmt,
|
||||
PrintVectorInitializer,
|
||||
PrintDeclFlags,
|
||||
PrintExprClassCast,
|
||||
PrintStaticArrayState,
|
||||
PrintProperty,
|
||||
PrintFlagDef,
|
||||
};
|
||||
|
||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
||||
{
|
||||
FLispString out;
|
||||
PrintNodes(out, root);
|
||||
return out;
|
||||
}
|
2129
source/common/scripting/frontend/zcc-parse.lemon
Normal file
2129
source/common/scripting/frontend/zcc-parse.lemon
Normal file
File diff suppressed because it is too large
Load diff
3039
source/common/scripting/frontend/zcc_compile.cpp
Normal file
3039
source/common/scripting/frontend/zcc_compile.cpp
Normal file
File diff suppressed because it is too large
Load diff
173
source/common/scripting/frontend/zcc_compile.h
Normal file
173
source/common/scripting/frontend/zcc_compile.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
#ifndef ZCC_COMPILE_H
|
||||
#define ZCC_COMPILE_H
|
||||
|
||||
#include <memory>
|
||||
#include "codegen.h"
|
||||
|
||||
struct Baggage;
|
||||
struct FPropertyInfo;
|
||||
class AActor;
|
||||
class FxExpression;
|
||||
typedef TDeletingArray<FxExpression*> FArgumentList;
|
||||
|
||||
|
||||
struct ZCC_StructWork
|
||||
{
|
||||
PSymbolTable TreeNodes;
|
||||
ZCC_Struct *strct;
|
||||
ZCC_Class *OuterDef;
|
||||
PClass *Outer;
|
||||
PSymbolTreeNode *node;
|
||||
TArray<ZCC_Enum *> Enums;
|
||||
TArray<ZCC_ConstantDef *> Constants;
|
||||
TArray<ZCC_VarDeclarator *> Fields;
|
||||
TArray<ZCC_FuncDeclarator *> Functions;
|
||||
TArray<ZCC_StaticArrayStatement *> Arrays;
|
||||
|
||||
ZCC_StructWork()
|
||||
{
|
||||
}
|
||||
|
||||
ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n, ZCC_Class *outer)
|
||||
{
|
||||
strct = s;
|
||||
node = n;
|
||||
OuterDef = outer;
|
||||
Outer = nullptr;
|
||||
};
|
||||
|
||||
FName NodeName() const
|
||||
{
|
||||
return strct->NodeName;
|
||||
}
|
||||
|
||||
PContainerType *Type()
|
||||
{
|
||||
return strct->Type;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct ZCC_ClassWork : public ZCC_StructWork
|
||||
{
|
||||
ZCC_Class *cls;
|
||||
TArray<ZCC_Default *> Defaults;
|
||||
TArray<ZCC_States *> States;
|
||||
TArray<ZCC_Property *> Properties;
|
||||
TArray<ZCC_FlagDef *> FlagDefs;
|
||||
|
||||
ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n)
|
||||
{
|
||||
strct = s;
|
||||
cls = s;
|
||||
node = n;
|
||||
OuterDef = nullptr;
|
||||
Outer = nullptr;
|
||||
}
|
||||
|
||||
PClass *ClassType()
|
||||
{
|
||||
return static_cast<PClassType *>(strct->Type)->Descriptor;
|
||||
}
|
||||
};
|
||||
|
||||
struct ZCC_MixinWork
|
||||
{
|
||||
PSymbolTable TreeNodes;
|
||||
ZCC_MixinDef *mixin;
|
||||
PSymbolTreeNode *node;
|
||||
|
||||
ZCC_MixinWork()
|
||||
{
|
||||
}
|
||||
|
||||
ZCC_MixinWork(ZCC_MixinDef *m, PSymbolTreeNode *n)
|
||||
{
|
||||
mixin = m;
|
||||
node = n;
|
||||
}
|
||||
};
|
||||
|
||||
struct ZCC_PropertyWork
|
||||
{
|
||||
ZCC_Property *prop;
|
||||
PSymbolTable *outputtable;
|
||||
};
|
||||
|
||||
struct ZCC_ConstantWork
|
||||
{
|
||||
ZCC_ConstantDef *node;
|
||||
PContainerType *cls;
|
||||
PSymbolTable *Outputtable;
|
||||
ExpVal constval;
|
||||
};
|
||||
|
||||
class ZCCCompiler
|
||||
{
|
||||
public:
|
||||
ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PNamespace *outnamespace, int lumpnum, const VersionInfo & ver);
|
||||
~ZCCCompiler();
|
||||
int Compile();
|
||||
|
||||
private:
|
||||
const char * GetStringConst(FxExpression *ex, FCompileContext &ctx);
|
||||
|
||||
int IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls);
|
||||
FString StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls);
|
||||
ZCC_MixinDef *ResolveMixinStmt(ZCC_MixinStmt *mixinStmt, EZCCMixinType type);
|
||||
void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode);
|
||||
void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer);
|
||||
void ProcessMixin(ZCC_MixinDef *cnode, PSymbolTreeNode *treenode);
|
||||
void CreateStructTypes();
|
||||
void CreateClassTypes();
|
||||
void CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PContainerType *cls, PSymbolTable *ot);
|
||||
void CompileAllConstants();
|
||||
void AddConstant(ZCC_ConstantWork &constant);
|
||||
bool CompileConstant(ZCC_ConstantWork *def);
|
||||
void CompileArrays(ZCC_StructWork *work);
|
||||
|
||||
void CompileAllFields();
|
||||
bool CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false);
|
||||
FString FlagsToString(uint32_t flags);
|
||||
PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember);
|
||||
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize);
|
||||
PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype);
|
||||
|
||||
void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass);
|
||||
|
||||
void InitFunctions();
|
||||
|
||||
TArray<ZCC_ConstantDef *> Constants;
|
||||
TArray<ZCC_StructWork *> Structs;
|
||||
TArray<ZCC_ClassWork *> Classes;
|
||||
TArray<ZCC_MixinWork *> Mixins;
|
||||
TArray<ZCC_PropertyWork *> Properties;
|
||||
VersionInfo mVersion;
|
||||
|
||||
PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false);
|
||||
|
||||
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table);
|
||||
ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
|
||||
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
|
||||
|
||||
|
||||
void Warn(ZCC_TreeNode *node, const char *msg, ...) GCCPRINTF(3,4);
|
||||
void Error(ZCC_TreeNode *node, const char *msg, ...) GCCPRINTF(3,4);
|
||||
void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr);
|
||||
|
||||
FxExpression *ConvertAST(PContainerType *cclass, ZCC_TreeNode *ast);
|
||||
FxExpression *ConvertNode(ZCC_TreeNode *node, bool substitute= false);
|
||||
FxExpression *ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Statement *nested);
|
||||
FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head);
|
||||
|
||||
DObject *Outer;
|
||||
PContainerType *ConvertClass; // class type to be used when resoving symbols while converting an AST
|
||||
PSymbolTable *GlobalTreeNodes;
|
||||
PNamespace *OutNamespace;
|
||||
ZCC_AST &AST;
|
||||
int Lump;
|
||||
};
|
||||
|
||||
void ZCC_InitConversions();
|
||||
|
||||
#endif
|
76
source/common/scripting/frontend/zcc_exprlist.h
Normal file
76
source/common/scripting/frontend/zcc_exprlist.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Name Token used in the code generator
|
||||
xx(Nil, TK_None)
|
||||
|
||||
xx(ID, TK_Identifier)
|
||||
xx(Super, TK_Super)
|
||||
xx(Null, TK_Null)
|
||||
xx(ConstValue, TK_Const)
|
||||
xx(FuncCall, '(')
|
||||
xx(ArrayAccess, TK_Array)
|
||||
xx(MemberAccess, '.')
|
||||
xx(ClassCast, TK_Class)
|
||||
xx(TypeRef, TK_Class)
|
||||
xx(Vector, TK_Vector2)
|
||||
|
||||
xx(PostInc, TK_Incr)
|
||||
xx(PostDec, TK_Decr)
|
||||
|
||||
xx(PreInc, TK_Incr)
|
||||
xx(PreDec, TK_Decr)
|
||||
xx(Negate, '-')
|
||||
xx(AntiNegate, '+')
|
||||
xx(BitNot, '~')
|
||||
xx(BoolNot, '!')
|
||||
xx(SizeOf, TK_SizeOf)
|
||||
xx(AlignOf, TK_AlignOf)
|
||||
|
||||
xx(Add, '+')
|
||||
xx(Sub, '-')
|
||||
xx(Mul, '*')
|
||||
xx(Div, '/')
|
||||
xx(Mod, '%')
|
||||
xx(Pow, TK_MulMul)
|
||||
xx(CrossProduct, TK_Cross)
|
||||
xx(DotProduct, TK_Dot)
|
||||
xx(LeftShift, TK_LShift)
|
||||
xx(RightShift, TK_RShift)
|
||||
xx(URightShift, TK_URShift)
|
||||
xx(Concat, TK_DotDot)
|
||||
|
||||
xx(LT, '<')
|
||||
xx(LTEQ, TK_Leq)
|
||||
xx(GT, '>')
|
||||
xx(GTEQ, TK_Geq)
|
||||
xx(LTGTEQ, TK_LtGtEq)
|
||||
xx(Is, TK_Is)
|
||||
|
||||
xx(EQEQ, TK_Eq)
|
||||
xx(NEQ, TK_Neq)
|
||||
xx(APREQ, TK_ApproxEq)
|
||||
|
||||
xx(BitAnd, '&')
|
||||
xx(BitOr, '|')
|
||||
xx(BitXor, '^')
|
||||
xx(BoolAnd, TK_AndAnd)
|
||||
xx(BoolOr, TK_OrOr)
|
||||
|
||||
xx(Assign, '=')
|
||||
xx(AddAssign, '+') // these are what the code generator needs, not what they represent.
|
||||
xx(SubAssign, '-')
|
||||
xx(MulAssign, '*')
|
||||
xx(DivAssign, '/')
|
||||
xx(ModAssign, '%')
|
||||
xx(LshAssign, TK_LShift)
|
||||
xx(RshAssign, TK_RShift)
|
||||
xx(URshAssign, TK_URShift)
|
||||
xx(AndAssign, '&')
|
||||
xx(OrAssign, '|')
|
||||
xx(XorAssign, '^')
|
||||
|
||||
xx(Scope, TK_ColonColon)
|
||||
|
||||
xx(Trinary, '?')
|
||||
|
||||
xx(Cast, TK_Coerce)
|
||||
|
||||
#undef xx
|
1381
source/common/scripting/frontend/zcc_parser.cpp
Normal file
1381
source/common/scripting/frontend/zcc_parser.cpp
Normal file
File diff suppressed because it is too large
Load diff
621
source/common/scripting/frontend/zcc_parser.h
Normal file
621
source/common/scripting/frontend/zcc_parser.h
Normal file
|
@ -0,0 +1,621 @@
|
|||
#ifndef ZCC_PARSER_H
|
||||
#define ZCC_PARSER_H
|
||||
|
||||
#include "memarena.h"
|
||||
#include "sc_man.h"
|
||||
#include "types.h"
|
||||
|
||||
struct ZCCToken
|
||||
{
|
||||
template <typename... Ts>
|
||||
struct TLargest;
|
||||
|
||||
template <typename T>
|
||||
struct TLargest<T>
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T, typename U, typename... Ts>
|
||||
struct TLargest<T, U, Ts...>
|
||||
{
|
||||
using Type = typename TLargest<
|
||||
typename std::conditional<
|
||||
(sizeof(T) > sizeof(U)), T, U
|
||||
>::type, Ts...
|
||||
>::Type;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int Int;
|
||||
double Float;
|
||||
FString *String;
|
||||
TLargest<decltype(Int), decltype(Float), decltype(String)>::Type Largest;
|
||||
};
|
||||
int SourceLoc;
|
||||
|
||||
ENamedName Name() { return ENamedName(Int); }
|
||||
};
|
||||
|
||||
// Variable / Function / Class modifiers
|
||||
enum
|
||||
{
|
||||
ZCC_Native = 1 << 0,
|
||||
ZCC_Static = 1 << 1,
|
||||
ZCC_Private = 1 << 2,
|
||||
ZCC_Protected = 1 << 3,
|
||||
ZCC_Latent = 1 << 4,
|
||||
ZCC_Final = 1 << 5,
|
||||
ZCC_Meta = 1 << 6,
|
||||
ZCC_Action = 1 << 7,
|
||||
ZCC_Deprecated = 1 << 8,
|
||||
ZCC_ReadOnly = 1 << 9,
|
||||
ZCC_FuncConst = 1 << 10,
|
||||
ZCC_Abstract = 1 << 11,
|
||||
ZCC_Extension = 1 << 12,
|
||||
ZCC_Virtual = 1 << 13,
|
||||
ZCC_Override = 1 << 14,
|
||||
ZCC_Transient = 1 << 15,
|
||||
ZCC_VarArg = 1 << 16,
|
||||
ZCC_UIFlag = 1 << 17, // there's also token called ZCC_UI
|
||||
ZCC_Play = 1 << 18,
|
||||
ZCC_ClearScope = 1 << 19,
|
||||
ZCC_VirtualScope = 1 << 20,
|
||||
ZCC_Version = 1 << 21,
|
||||
ZCC_Internal = 1 << 22,
|
||||
};
|
||||
|
||||
// Function parameter modifiers
|
||||
enum
|
||||
{
|
||||
ZCC_In = 1 << 0,
|
||||
ZCC_Out = 1 << 1,
|
||||
ZCC_Optional = 1 << 2,
|
||||
};
|
||||
|
||||
|
||||
// Syntax tree structures.
|
||||
// [pbeta] Any changes to AST node structure or new node types require TreeNodeDeepCopy in zcc_parser.cpp to be updated!
|
||||
enum EZCCTreeNodeType
|
||||
{
|
||||
AST_Identifier,
|
||||
AST_Class,
|
||||
AST_Struct,
|
||||
AST_Enum,
|
||||
AST_EnumTerminator,
|
||||
AST_States,
|
||||
AST_StatePart,
|
||||
AST_StateLabel,
|
||||
AST_StateStop,
|
||||
AST_StateWait,
|
||||
AST_StateFail,
|
||||
AST_StateLoop,
|
||||
AST_StateGoto,
|
||||
AST_StateLine,
|
||||
AST_VarName,
|
||||
AST_VarInit,
|
||||
AST_Type,
|
||||
AST_BasicType,
|
||||
AST_MapType,
|
||||
AST_DynArrayType,
|
||||
AST_ClassType,
|
||||
AST_Expression,
|
||||
AST_ExprID,
|
||||
AST_ExprTypeRef,
|
||||
AST_ExprConstant,
|
||||
AST_ExprFuncCall,
|
||||
AST_ExprMemberAccess,
|
||||
AST_ExprUnary,
|
||||
AST_ExprBinary,
|
||||
AST_ExprTrinary,
|
||||
AST_FuncParm,
|
||||
AST_Statement,
|
||||
AST_CompoundStmt,
|
||||
AST_ContinueStmt,
|
||||
AST_BreakStmt,
|
||||
AST_ReturnStmt,
|
||||
AST_ExpressionStmt,
|
||||
AST_IterationStmt,
|
||||
AST_IfStmt,
|
||||
AST_SwitchStmt,
|
||||
AST_CaseStmt,
|
||||
AST_AssignStmt,
|
||||
AST_LocalVarStmt,
|
||||
AST_FuncParamDecl,
|
||||
AST_ConstantDef,
|
||||
AST_Declarator,
|
||||
AST_VarDeclarator,
|
||||
AST_FuncDeclarator,
|
||||
AST_Default,
|
||||
AST_FlagStmt,
|
||||
AST_PropertyStmt,
|
||||
AST_VectorValue,
|
||||
AST_DeclFlags,
|
||||
AST_ClassCast,
|
||||
AST_StaticArrayStatement,
|
||||
AST_Property,
|
||||
AST_FlagDef,
|
||||
AST_MixinDef,
|
||||
AST_MixinStmt,
|
||||
|
||||
NUM_AST_NODE_TYPES
|
||||
};
|
||||
|
||||
enum EZCCBuiltinType
|
||||
{
|
||||
ZCC_SInt8,
|
||||
ZCC_UInt8,
|
||||
ZCC_SInt16,
|
||||
ZCC_UInt16, // smaller than 32 bit types are only valid in structs, classes and arrays.
|
||||
ZCC_SInt32,
|
||||
ZCC_UInt32,
|
||||
ZCC_IntAuto, // for enums, autoselect appropriately sized int
|
||||
|
||||
ZCC_Bool,
|
||||
ZCC_Float64,
|
||||
ZCC_FloatAuto, // 32-bit in structs/classes, 64-bit everywhere else
|
||||
ZCC_String,
|
||||
ZCC_Vector2,
|
||||
ZCC_Vector3,
|
||||
ZCC_Name,
|
||||
|
||||
ZCC_Color, // special types for ZDoom.
|
||||
ZCC_State,
|
||||
ZCC_Sound,
|
||||
|
||||
ZCC_UserType,
|
||||
ZCC_NativeType,
|
||||
ZCC_Let,
|
||||
|
||||
ZCC_NUM_BUILT_IN_TYPES
|
||||
};
|
||||
|
||||
enum EZCCMixinType
|
||||
{
|
||||
ZCC_Mixin_Class,
|
||||
|
||||
ZCC_NUM_MIXIN_TYPES
|
||||
};
|
||||
|
||||
enum EZCCExprType
|
||||
{
|
||||
#define xx(a,z) PEX_##a,
|
||||
#include "zcc_exprlist.h"
|
||||
|
||||
PEX_COUNT_OF
|
||||
};
|
||||
|
||||
struct ZCC_TreeNode
|
||||
{
|
||||
// This tree node's siblings are stored in a circular linked list.
|
||||
// When you get back to this node, you know you've been through
|
||||
// the whole list.
|
||||
ZCC_TreeNode *SiblingNext;
|
||||
ZCC_TreeNode *SiblingPrev;
|
||||
|
||||
// can't use FScriptPosition, because the string wouldn't have a chance to
|
||||
// destruct if we did that.
|
||||
FString *SourceName;
|
||||
int SourceLump;
|
||||
int SourceLoc;
|
||||
|
||||
// Node type is one of the node types above, which corresponds with
|
||||
// one of the structures below.
|
||||
EZCCTreeNodeType NodeType;
|
||||
|
||||
operator FScriptPosition()
|
||||
{
|
||||
return FScriptPosition(*SourceName, SourceLoc);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void AppendTreeNodeSibling(ZCC_TreeNode *thisnode, ZCC_TreeNode *sibling);
|
||||
|
||||
struct ZCC_Identifier : ZCC_TreeNode
|
||||
{
|
||||
ENamedName Id;
|
||||
};
|
||||
|
||||
struct ZCC_NamedNode : ZCC_TreeNode
|
||||
{
|
||||
ENamedName NodeName;
|
||||
PSymbolType *Symbol;
|
||||
};
|
||||
|
||||
struct ZCC_Struct : ZCC_NamedNode
|
||||
{
|
||||
uint32_t Flags;
|
||||
ZCC_TreeNode *Body;
|
||||
PContainerType *Type;
|
||||
VersionInfo Version;
|
||||
};
|
||||
|
||||
struct ZCC_Property : ZCC_NamedNode
|
||||
{
|
||||
ZCC_TreeNode *Body;
|
||||
};
|
||||
|
||||
struct ZCC_FlagDef : ZCC_NamedNode
|
||||
{
|
||||
ENamedName RefName;
|
||||
int BitValue;
|
||||
};
|
||||
|
||||
struct ZCC_Class : ZCC_Struct
|
||||
{
|
||||
ZCC_Identifier *ParentName;
|
||||
ZCC_Identifier *Replaces;
|
||||
|
||||
PClass *CType() { return static_cast<PClassType *>(Type)->Descriptor; }
|
||||
};
|
||||
|
||||
struct ZCC_MixinDef : ZCC_NamedNode
|
||||
{
|
||||
ZCC_TreeNode *Body;
|
||||
|
||||
EZCCMixinType MixinType;
|
||||
};
|
||||
|
||||
struct ZCC_Enum : ZCC_NamedNode
|
||||
{
|
||||
EZCCBuiltinType EnumType;
|
||||
struct ZCC_ConstantDef *Elements;
|
||||
};
|
||||
|
||||
struct ZCC_EnumTerminator : ZCC_TreeNode
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_States : ZCC_TreeNode
|
||||
{
|
||||
struct ZCC_StatePart *Body;
|
||||
ZCC_Identifier *Flags;
|
||||
};
|
||||
|
||||
struct ZCC_StatePart : ZCC_TreeNode
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_StateLabel : ZCC_StatePart
|
||||
{
|
||||
ENamedName Label;
|
||||
};
|
||||
|
||||
struct ZCC_StateStop : ZCC_StatePart
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_StateWait : ZCC_StatePart
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_StateFail : ZCC_StatePart
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_StateLoop : ZCC_StatePart
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_Expression : ZCC_TreeNode
|
||||
{
|
||||
EZCCExprType Operation;
|
||||
PType *Type;
|
||||
|
||||
// Repurposes this node as an error node
|
||||
void ToErrorNode()
|
||||
{
|
||||
Type = TypeError;
|
||||
Operation = PEX_Nil;
|
||||
NodeType = AST_Expression;
|
||||
}
|
||||
};
|
||||
|
||||
struct ZCC_StateGoto : ZCC_StatePart
|
||||
{
|
||||
ZCC_Identifier *Qualifier;
|
||||
ZCC_Identifier *Label;
|
||||
ZCC_Expression *Offset;
|
||||
};
|
||||
|
||||
struct ZCC_StateLine : ZCC_StatePart
|
||||
{
|
||||
FString *Sprite;
|
||||
BITFIELD bBright : 1;
|
||||
BITFIELD bFast : 1;
|
||||
BITFIELD bSlow : 1;
|
||||
BITFIELD bNoDelay : 1;
|
||||
BITFIELD bCanRaise : 1;
|
||||
FString *Frames;
|
||||
ZCC_Expression *Duration;
|
||||
ZCC_Expression *Offset;
|
||||
ZCC_ExprConstant *Lights;
|
||||
ZCC_TreeNode *Action;
|
||||
};
|
||||
|
||||
struct ZCC_VarName : ZCC_TreeNode
|
||||
{
|
||||
ENamedName Name;
|
||||
ZCC_Expression *ArraySize; // NULL if not an array
|
||||
};
|
||||
|
||||
struct ZCC_VarInit : ZCC_VarName
|
||||
{
|
||||
ZCC_Expression *Init;
|
||||
bool InitIsArray; // this is needed to distinguish one-element arrays from raw elements.
|
||||
};
|
||||
|
||||
struct ZCC_Type : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Expression *ArraySize; // NULL if not an array
|
||||
};
|
||||
|
||||
struct ZCC_BasicType : ZCC_Type
|
||||
{
|
||||
EZCCBuiltinType Type;
|
||||
ZCC_Identifier *UserType;
|
||||
bool isconst;
|
||||
};
|
||||
|
||||
struct ZCC_MapType : ZCC_Type
|
||||
{
|
||||
ZCC_Type *KeyType;
|
||||
ZCC_Type *ValueType;
|
||||
};
|
||||
|
||||
struct ZCC_DynArrayType : ZCC_Type
|
||||
{
|
||||
ZCC_Type *ElementType;
|
||||
};
|
||||
|
||||
struct ZCC_ClassType : ZCC_Type
|
||||
{
|
||||
ZCC_Identifier *Restriction;
|
||||
};
|
||||
|
||||
struct ZCC_ExprID : ZCC_Expression
|
||||
{
|
||||
ENamedName Identifier;
|
||||
};
|
||||
|
||||
struct ZCC_ExprTypeRef : ZCC_Expression
|
||||
{
|
||||
PType *RefType;
|
||||
};
|
||||
|
||||
struct ZCC_ExprConstant : ZCC_Expression
|
||||
{
|
||||
// [pbeta] The ZCC_ExprConstant case in TreeNodeDeepCopy in zcc_parser.cpp
|
||||
// must be updated if this union is changed!
|
||||
union
|
||||
{
|
||||
FString *StringVal;
|
||||
int IntVal;
|
||||
unsigned int UIntVal;
|
||||
double DoubleVal;
|
||||
};
|
||||
};
|
||||
|
||||
struct ZCC_FuncParm : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Expression *Value;
|
||||
ENamedName Label;
|
||||
};
|
||||
|
||||
struct ZCC_ExprFuncCall : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Function;
|
||||
ZCC_FuncParm *Parameters;
|
||||
};
|
||||
|
||||
struct ZCC_ClassCast : ZCC_Expression
|
||||
{
|
||||
ENamedName ClassName;
|
||||
ZCC_FuncParm *Parameters;
|
||||
};
|
||||
|
||||
struct ZCC_ExprMemberAccess : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Left;
|
||||
ENamedName Right;
|
||||
};
|
||||
|
||||
struct ZCC_ExprUnary : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Operand;
|
||||
};
|
||||
|
||||
struct ZCC_ExprBinary : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Left;
|
||||
ZCC_Expression *Right;
|
||||
};
|
||||
|
||||
struct ZCC_ExprTrinary : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Test;
|
||||
ZCC_Expression *Left;
|
||||
ZCC_Expression *Right;
|
||||
};
|
||||
|
||||
struct ZCC_VectorValue : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *X, *Y, *Z;
|
||||
};
|
||||
|
||||
struct ZCC_Statement : ZCC_TreeNode
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_StaticArrayStatement : ZCC_Statement
|
||||
{
|
||||
ZCC_Type *Type;
|
||||
ENamedName Id;
|
||||
ZCC_Expression *Values;
|
||||
};
|
||||
|
||||
struct ZCC_CompoundStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Statement *Content;
|
||||
};
|
||||
|
||||
struct ZCC_ContinueStmt : ZCC_Statement
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_BreakStmt : ZCC_Statement
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_ReturnStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *Values;
|
||||
};
|
||||
|
||||
struct ZCC_ExpressionStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *Expression;
|
||||
};
|
||||
|
||||
struct ZCC_IterationStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *LoopCondition;
|
||||
ZCC_Statement *LoopStatement;
|
||||
ZCC_Statement *LoopBumper;
|
||||
|
||||
// Should the loop condition be checked at the
|
||||
// start of the loop (before the LoopStatement)
|
||||
// or at the end (after the LoopStatement)?
|
||||
enum { Start, End } CheckAt;
|
||||
};
|
||||
|
||||
struct ZCC_IfStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *Condition;
|
||||
ZCC_Statement *TruePath;
|
||||
ZCC_Statement *FalsePath;
|
||||
};
|
||||
|
||||
struct ZCC_SwitchStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *Condition;
|
||||
ZCC_Statement *Content;
|
||||
};
|
||||
|
||||
struct ZCC_CaseStmt : ZCC_Statement
|
||||
{
|
||||
// A NULL Condition represents the default branch
|
||||
ZCC_Expression *Condition;
|
||||
};
|
||||
|
||||
struct ZCC_AssignStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Expression *Dests;
|
||||
ZCC_Expression *Sources;
|
||||
int AssignOp;
|
||||
};
|
||||
|
||||
struct ZCC_LocalVarStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Type *Type;
|
||||
ZCC_VarInit *Vars;
|
||||
};
|
||||
|
||||
struct ZCC_FuncParamDecl : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Type *Type;
|
||||
ZCC_Expression *Default;
|
||||
ENamedName Name;
|
||||
int Flags;
|
||||
};
|
||||
|
||||
struct ZCC_DeclFlags : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Identifier *Id;
|
||||
FString *DeprecationMessage;
|
||||
VersionInfo Version;
|
||||
int Flags;
|
||||
};
|
||||
|
||||
struct ZCC_ConstantDef : ZCC_NamedNode
|
||||
{
|
||||
ZCC_Expression *Value;
|
||||
PSymbolConst *Symbol;
|
||||
ZCC_Enum *Type; // gets set when the constant originates from an enum.
|
||||
};
|
||||
|
||||
struct ZCC_Declarator : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Type *Type;
|
||||
int Flags;
|
||||
VersionInfo Version;
|
||||
};
|
||||
|
||||
// A variable in a class or struct.
|
||||
struct ZCC_VarDeclarator : ZCC_Declarator
|
||||
{
|
||||
ZCC_VarName *Names;
|
||||
FString *DeprecationMessage;
|
||||
};
|
||||
|
||||
// A function in a class.
|
||||
struct ZCC_FuncDeclarator : ZCC_Declarator
|
||||
{
|
||||
ZCC_FuncParamDecl *Params;
|
||||
ENamedName Name;
|
||||
ZCC_Statement *Body;
|
||||
ZCC_Identifier *UseFlags;
|
||||
FString *DeprecationMessage;
|
||||
};
|
||||
|
||||
struct ZCC_Default : ZCC_CompoundStmt
|
||||
{
|
||||
};
|
||||
|
||||
struct ZCC_PropertyStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Identifier *Prop;
|
||||
ZCC_Expression *Values;
|
||||
};
|
||||
|
||||
|
||||
struct ZCC_FlagStmt : ZCC_Statement
|
||||
{
|
||||
ZCC_Identifier *name;
|
||||
bool set;
|
||||
};
|
||||
|
||||
struct ZCC_MixinStmt : ZCC_Statement
|
||||
{
|
||||
ENamedName MixinName;
|
||||
};
|
||||
|
||||
FString ZCC_PrintAST(ZCC_TreeNode *root);
|
||||
|
||||
|
||||
struct ZCC_AST
|
||||
{
|
||||
ZCC_AST() : TopNode(NULL) {}
|
||||
ZCC_TreeNode *InitNode(size_t size, EZCCTreeNodeType type, ZCC_TreeNode *basis);
|
||||
|
||||
FSharedStringArena Strings;
|
||||
FMemArena SyntaxArena;
|
||||
struct ZCC_TreeNode *TopNode;
|
||||
VersionInfo ParseVersion;
|
||||
};
|
||||
|
||||
struct ZCCParseState : public ZCC_AST
|
||||
{
|
||||
ZCCParseState(FScanner *scanner = nullptr) : sc(scanner) {}
|
||||
ZCC_TreeNode *InitNode(size_t size, EZCCTreeNodeType type);
|
||||
|
||||
FScanner *sc;
|
||||
};
|
||||
|
||||
const char *GetMixinTypeString(EZCCMixinType type);
|
||||
|
||||
ZCC_TreeNode *TreeNodeDeepCopy(ZCC_AST *ast, ZCC_TreeNode *orig, bool copySiblings);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue