#pragma once //#ifndef REAL_BUILD # include "externals.hh" //#endif #include namespace opast { using namespace ebcl; class T_RootNode; class A_Node { public: enum E_Type { ROOT , // DECL_INIT , DECL_FRAME , DECL_FN , // OP_SET , // EXPR_ADD , EXPR_MUL , EXPR_SUB , EXPR_DIV , EXPR_VAR , EXPR_CONST , }; private: const E_Type type_; A_Node* const parent_; T_SRDLocation location_; protected: explicit A_Node( const E_Type type , A_Node* const parent ) noexcept; public: virtual ~A_Node( ) = 0; E_Type type( ) const noexcept { return type_; } T_SRDLocation& location( ) noexcept { return location_; } T_SRDLocation const& location( ) const noexcept { return location_; } A_Node& parent( ) const noexcept { assert( parent_ ); return *parent_; } T_RootNode& root( ) const noexcept; }; /*----------------------------------------------------------------------------*/ // Function-like nodes class A_FuncNode : public A_Node { private: T_String name_; protected: // For init or frame entry points. // isInit = true => init entry point // isInit = false => frame entry point explicit A_FuncNode( bool isInit , T_RootNode* const parent ) noexcept; // For normal functions explicit A_FuncNode( T_String const& name , T_RootNode* const parent ) noexcept; public: T_String const& name( ) const noexcept { return name_; } }; // Root node, keeps track of the whole tree and related data (function table, // assets...) class T_RootNode : public A_Node { private: T_ObjectTable< T_String , T_OwnPtr< A_FuncNode > > functions_; public: T_RootNode( ) noexcept; // Return type for addFunction. We'll always return a reference to a // function node (which may or may not be the same as the initial one, // if there were duplicates), and we'll return the location of the // initial function in the case of a duplicate. struct T_AddFunctionResult { A_FuncNode& function; T_Optional< T_SRDLocation > dupLocation; T_AddFunctionResult( A_FuncNode& function ) noexcept : function{ function } , dupLocation{} {} T_AddFunctionResult( A_FuncNode& function , T_SRDLocation const& dupLocation ) noexcept : function{ function } , dupLocation{ dupLocation } {} }; // Attempts to add a function. If the function is already present in // the table, the result will be set up with the previous declaration's // location, and the specified function will not be modified (a duplicate // entry will be added to the table instead). T_AddFunctionResult addFunction( T_OwnPtr< A_FuncNode >& function ) noexcept; }; /*----------------------------------------------------------------------------*/ // Init & frame functions class T_SpecialFuncNode : public A_FuncNode { public: T_SpecialFuncNode( bool isInit , T_RootNode& parent ) noexcept; }; // Normal functions class T_FuncNode : public A_FuncNode { private: T_AutoArray< T_String , 8 > argNames_; T_AutoArray< T_SRDLocation , 8 > argLocations_; public: T_FuncNode( T_String const& name , T_RootNode& parent ) noexcept; // Add an argument. If the argument is a duplicate, return the location // of the initial argument. T_Optional< T_SRDLocation > addArgument( T_SRDToken const& token ) noexcept; }; /*----------------------------------------------------------------------------*/ class T_Parser : public A_PrivateImplementation { private: T_Array< T_SRDError > errors_; T_OwnPtr< T_RootNode > rootNode_; public: T_Parser( ) noexcept; bool parse( T_SRDList const& input ) noexcept; T_Array< T_SRDError > const& errors( ) const noexcept { return errors_; } T_OwnPtr< T_RootNode > result( ) noexcept { return std::move( rootNode_ ); } }; } // namespace opast