mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-25 21:41:44 +00:00
648 lines
11 KiB
C++
648 lines
11 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_MapIteratorType,
|
|
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_AssignDeclStmt,
|
|
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,
|
|
AST_ArrayIterationStmt,
|
|
|
|
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_MapIteratorType : 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_ArrayIterationStmt : ZCC_Statement
|
|
{
|
|
ZCC_VarName* ItName;
|
|
ZCC_Expression* ItArray;
|
|
ZCC_Statement* LoopStatement;
|
|
};
|
|
|
|
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_AssignDeclStmt : ZCC_Statement
|
|
{
|
|
ZCC_Identifier *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(const 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
|