#ifndef ZCC_PARSER_H #define ZCC_PARSER_H #include "memarena.h" #include "sc_man.h" #include "types.h" struct ZCCToken { template struct TLargest; template struct TLargest { using Type = T; }; template struct TLargest { using Type = typename TLargest< typename std::conditional< (sizeof(T) > sizeof(U)), T, U >::type, Ts... >::Type; }; union { int Int; double Float; FString *String; TLargest::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(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); // Main entry point for the parser. Returns some data needed by the compiler. PNamespace* ParseOneScript(const int baselump, ZCCParseState& state); #endif