mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-09 10:40:56 +00:00
b1a83bfd26
* everything related to scripting is now placed in a subdirectory 'scripting', which itself is separated into DECORATE, ZSCRIPT, the VM and code generation. * a few items have been moved to different headers so that the DECORATE parser definitions can mostly be kept local. The only exception at the moment is the flags interface on which 3 source files depend.
904 lines
20 KiB
C++
904 lines
20 KiB
C++
/*
|
|
** 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 "sc_man.h"
|
|
#include "memarena.h"
|
|
#include "zcc_parser.h"
|
|
#include "zcc-parse.h"
|
|
|
|
class FLispString;
|
|
extern void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *);
|
|
|
|
static const char *BuiltInTypeNames[] =
|
|
{
|
|
"sint8", "uint8",
|
|
"sint16", "uint16",
|
|
"sint32", "uint32",
|
|
"intauto",
|
|
|
|
"bool",
|
|
"float32", "float64", "floatauto",
|
|
"string",
|
|
"vector2",
|
|
"vector3",
|
|
"vector4",
|
|
"name",
|
|
"color",
|
|
"state",
|
|
"sound",
|
|
|
|
"usertype",
|
|
|
|
};
|
|
|
|
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(long(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 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->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 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)
|
|
{
|
|
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-%s", ZCC_OpInfo[type].OpName);
|
|
}
|
|
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->IsKindOf(RUNTIME_CLASS(PInt)))
|
|
{
|
|
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 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 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");
|
|
switch (snode->AssignOp)
|
|
{
|
|
case ZCC_EQ: out.AddChar('='); break;
|
|
case ZCC_MULEQ: out.Add("*=", 2); break;
|
|
case ZCC_DIVEQ: out.Add("/=", 2); break;
|
|
case ZCC_MODEQ: out.Add("%=", 2); break;
|
|
case ZCC_ADDEQ: out.Add("+=", 2); break;
|
|
case ZCC_SUBEQ: out.Add("-=", 2); break;
|
|
case ZCC_LSHEQ: out.Add("<<=", 2); break;
|
|
case ZCC_RSHEQ: out.Add(">>=", 2); break;
|
|
case ZCC_ANDEQ: out.Add("&=", 2); break;
|
|
case ZCC_OREQ: out.Add("|=", 2); break;
|
|
case ZCC_XOREQ: out.Add("^=", 2); break;
|
|
default: BadAssignOp(out, snode->AssignOp); break;
|
|
}
|
|
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);
|
|
PrintNodes(out, snode->Inits);
|
|
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->Type);
|
|
out.AddName(dnode->Name);
|
|
PrintNodes(out, dnode->Params);
|
|
PrintNodes(out, dnode->Body, false);
|
|
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,
|
|
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
|
|
};
|
|
|
|
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
|
{
|
|
FLispString out;
|
|
PrintNodes(out, root);
|
|
return out;
|
|
}
|