raze/source/common/scripting/frontend/zcc_parser.h
Christoph Oelckers 8806fb930b - Backend update from GZDoom
* Vector 4 in zscript
* garbage collector fixes
2022-11-12 10:45:39 +01:00

625 lines
10 KiB
C++

#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_Vector4,
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, *W;
};
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);
// Main entry point for the parser. Returns some data needed by the compiler.
PNamespace* ParseOneScript(const int baselump, ZCCParseState& state);
#endif