#include "opast.hh" using namespace ebcl; using namespace opast; /*= A_Node ===================================================================*/ A_Node::A_Node( const E_Type type , A_Node* const parent ) noexcept : type_( type ) , parent_( parent ) { assert( ( type == ROOT && !parent ) || ( type != ROOT && parent ) ); } A_Node::~A_Node( ) { } T_RootNode& A_Node::root( ) const noexcept { A_Node const* node( this ); while ( node->parent_ ) { node = node->parent_; } assert( node ); assert( node->type_ == ROOT ); return *dynamic_cast< T_RootNode* >( const_cast< A_Node* >( node ) ); } /*= A_FuncNode ===============================================================*/ A_FuncNode::A_FuncNode( const bool isInit , T_RootNode* const root ) noexcept : A_Node( isInit ? DECL_INIT : DECL_FRAME , root ) , name_( isInit ? "*init*" : "*frame*" ) { } A_FuncNode::A_FuncNode( T_String const& name , T_RootNode* const root ) noexcept : A_Node( DECL_FN , root ) , name_( name ) { } /*= T_RootNode ===============================================================*/ T_RootNode::T_RootNode( ) noexcept : A_Node( ROOT , nullptr ) , functions_( []( T_OwnPtr< A_FuncNode > const& f ) { return f->name( ); } ) { } T_RootNode::T_AddFunctionResult T_RootNode::addFunction( T_OwnPtr< A_FuncNode >& function ) noexcept { T_String const& fn( function->name( ) ); auto const* const pf( functions_.get( fn ) ); if ( !pf ) { auto* const rv( function.get( ) ); functions_.add( std::move( function ) ); return *rv; } T_String dfn; uint32_t dupCtr( 0 ); do { T_StringBuilder fnsb; fnsb << fn << " dup " << dupCtr ++; dfn = std::move( fnsb ); } while ( functions_.contains( dfn ) ); T_OwnPtr< A_FuncNode > df( NewOwned< T_FuncNode >( dfn , *this ) ); auto* const rv( df.get( ) ); functions_.add( std::move( df ) ); return T_AddFunctionResult{ *rv , (*pf)->location( ) }; } /*= T_SpecialFuncNode ========================================================*/ T_SpecialFuncNode::T_SpecialFuncNode( bool isInit , T_RootNode& parent ) noexcept : A_FuncNode( isInit , &parent ) { } /*= T_FuncNode ===============================================================*/ T_FuncNode::T_FuncNode( T_String const& name , T_RootNode& parent ) noexcept : A_FuncNode( name , &parent ) { } T_Optional< T_SRDLocation > T_FuncNode::addArgument( T_SRDToken const& token ) noexcept { assert( token.type( ) == E_SRDTokenType::WORD ); assert( token.hasLocation( ) ); const auto pnp( argNames_.indexOf( token.stringValue( ) ) ); if ( pnp != -1 ) { return argLocations_[ pnp ]; } argNames_.add( token.stringValue( ) ); argLocations_.add( token.location( ) ); return {}; } /*= T_Parser =================================================================*/ namespace { struct T_ParserImpl_ { T_OwnPtr< T_RootNode >& root; T_Array< T_SRDError >& errors; T_ParserImpl_( T_Array< T_SRDError >* errors , T_OwnPtr< T_RootNode >* root ) noexcept; void parseFunction( T_SRDList const& funcList ) noexcept; }; T_ParserImpl_::T_ParserImpl_( T_Array< T_SRDError >* const errors , T_OwnPtr< T_RootNode >* const root ) noexcept : root( *root ) , errors( *errors ) { } void T_ParserImpl_::parseFunction( T_SRDList const& funcList ) noexcept { assert( funcList.size( ) != 0 ); auto const& fw( funcList[ 0 ] ); if ( fw.type( ) != E_SRDTokenType::WORD || ( fw.stringValue( ) != "init" && fw.stringValue( ) != "frame" && fw.stringValue( ) != "fn" ) ) { errors.addNew( "init, frame or fn expected" , fw.location( ) ); return; } T_String const& ftw( fw.stringValue( ) ); T_OwnPtr< A_FuncNode > fn; if ( ftw == "fn" ) { if ( funcList.size( ) < 3 ) { errors.addNew( "function name and arguments expected" , fw.location( ) ); return; } if ( funcList[ 1 ].type( ) != E_SRDTokenType::WORD ) { errors.addNew( "function name expected" , funcList[ 1 ].location( ) ); return; } fn = NewOwned< T_FuncNode >( funcList[ 1 ].stringValue( ) , *root ); // TODO parseFunctionArguments( funcList[ 2 ] ); } else { fn = NewOwned< T_SpecialFuncNode >( ftw == "init" , *root ); } fn->location( ) = fw.location( ); const auto af( root->addFunction( fn ) ); if ( af.dupLocation.present( ) ) { T_StringBuilder esb( "duplicate " ); switch ( fn->type( ) ) { case A_Node::DECL_FN: esb << "function '" << fn->name( ) << "'"; break; case A_Node::DECL_INIT: esb << "initialisation function"; break; case A_Node::DECL_FRAME: esb << "frame function"; break; default: std::abort( ); } esb << "; previous declaration: " << *af.dupLocation.target( ); errors.addNew( std::move( esb ) , fw.location( ) ); } // TODO parseInstructions( fn->instructions , funcList , // ftw == "fn" ? 3 : 1 ); } } // namespace /*----------------------------------------------------------------------------*/ T_Parser::T_Parser( ) noexcept : A_PrivateImplementation( new T_ParserImpl_( &errors_ , &rootNode_ ) ) , errors_( 64 ) , rootNode_{} {} bool T_Parser::parse( T_SRDList const& input ) noexcept { errors_.clear( ); rootNode_ = NewOwned< T_RootNode >( ); for ( auto const& t : input ) { if ( t.type( ) == E_SRDTokenType::LIST && t.list( ).size( ) > 0 ) { p< T_ParserImpl_ >( ).parseFunction( t.list( ) ); } else { errors_.addNew( "Function or special block expected" , t.location( ) ); } } return errors_.empty( ); }