【表达式树】( 二叉树 | 逆波兰式 | RAII模式 | 工厂模式 | 解析器模式 | 运行时多态 )

 

#include <unordered_map>
#include <functional>
#include <sstream>
#include <cctype>
#include <stack>
#include <utility>
#include <type_traits>
#include <tuple>
#include <concepts>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <new>
#include <limits>
#include <iomanip>

template < class Ty >
struct Mallocator{
	using propagate_on_container_copy_assignment = std::true_type;
	typedef ::std::decay_t< Ty > value_type;
	typedef ::std::add_pointer< value_type >::type pointer;
	typedef ::std::size_t size_type;
	::std::allocator<value_type> allocator;

	Mallocator( void ) = default;
	template < class U >
	explicit constexpr Mallocator ( const Mallocator < U >& ) noexcept{}
	pointer allocate( size_type n ){
		if( n > ::std::numeric_limits< size_type >::max() / sizeof( value_type ) )
			throw ::std::bad_array_new_length();
		if( auto  p = static_cast< pointer >( ::std::malloc( n * sizeof( value_type ) ) ) ){
			report( p, n );
			return p;
		}
		throw ::std::bad_alloc();
	}

	void deallocate( pointer p, size_type n ) noexcept{
		report( p, n, 0 );
		::std::free( p );
	}
	
    template <typename U>
    void destroy(U* p) {
        ::std::allocator_traits<std::allocator<Ty>>::destroy(allocator, p);
    }
    
    template <typename U>
    using rebind = Mallocator<U>;
private:
	void report( pointer p, size_type n, bool alloc = true ) const{
		::std::cout << ::std::hex << ::std::showbase
					<< reinterpret_cast< void * >( p )
					<< ::std::dec
					<< (alloc ? "alloc": "dealloc")
					<< sizeof( value_type ) * n
					<< "bytes";
		::std::endl( ::std::cout );
	}
};

template < class T, class U >
inline constexpr
bool operator==( const Mallocator <T>&, const Mallocator <U>& ) { return true; }
template < class T, class U >
inline constexpr
bool operator!=( const Mallocator <T>&, const Mallocator <U>& ) { return false; }

class expression{
public:
    virtual ~expression( void ) {}
    virtual int interprete( ::std::unordered_map< char, int >& map ) const = 0;
};

using abstr_expr_uptr =
	::std::unique_ptr< expression, Mallocator< expression > >;

class variable : public expression{
protected: char key;
public:
    variable( const char& key ) : key( key ) {}
    inline virtual
    int interprete( ::std::unordered_map< char, int >& assign_map ) const {
        return assign_map[ key ];
    }
};

class arthmetic : public expression{
protected:
    abstr_expr_uptr lopd, ropd;
private: ::std::function< int( int, int ) > f;
public:
    template < class Callable ,
            class = typename ::std::enable_if_t<
            ::std::is_same_v<
            int, typename ::std::result_of<
            Callable&&( int, int ) >::type > > >
	    requires ::std::regular_invocable< Callable, int , int >
    arthmetic( abstr_expr_uptr lopd,
               abstr_expr_uptr ropd,
               Callable&& f )
        :lopd( std::move( lopd ) )
        ,ropd( std::move( ropd ) )
        ,f( ::std::forward< ::std::decay_t< Callable > >( f ) ) {}
    inline virtual
    int interprete( ::std::unordered_map< char, int >& assign_map ) const override{
        return ::std::invoke( f, lopd->interprete( assign_map ), ropd->interprete( assign_map ) );
    }
};

::std::unordered_map< char, int >
arthmetic_priority_map( { {'+', 0},
                 		  {'-', 1},
                          {'*', 2},
                          {'/', 3} } );

template < typename Ty >
Ty get( ::std::stack< Ty >& Stk ){
	if( !Stk.empty() ){
	    Ty result = std::move( Stk.top() );
	    Stk.pop();
	    return ::std::move( result );
	}
	
}

class factory{
public:
    static abstr_expr_uptr
    create_arthmetic( char oper,
            abstr_expr_uptr lopd,
            abstr_expr_uptr ropd ){
        switch( oper ){
            case '+': return abstr_expr_uptr(new arthmetic( ::std::move( lopd ), ::std::move( ropd ), [](int v1, int v2)->int{ return v1 + v2; } ) );
            case '-': return abstr_expr_uptr(new arthmetic( ::std::move( lopd ), ::std::move( ropd ), [](int v1, int v2)->int{ return v1 - v2; } ) );
            case '*': return abstr_expr_uptr(new arthmetic( ::std::move( lopd ), ::std::move( ropd ), [](int v1, int v2)->int{ return v1 * v2; } ) );
            case '/': return abstr_expr_uptr(new arthmetic( ::std::move( lopd ), ::std::move( ropd ), [](int v1, int v2)->int{ return v1 / v2; } ) );
            default: return nullptr;
        }
    }
    static abstr_expr_uptr
    create_variable( char var ){
		return abstr_expr_uptr( new variable( var ) );
	}
};

abstr_expr_uptr analyse( ::std::istringstream& out ){
    char _Char { 0 };
    ::std::stack< abstr_expr_uptr > variableStack;
    ::std::stack< char > arthmeticStack;

    while( (bool)out.get( _Char ) ){
        if( ::std::isalpha( _Char ) )
            variableStack.push( factory::create_variable( _Char ) );
        else if ( _Char == '(' ) variableStack.push( analyse( out ) );
        else if( _Char == ')' ) {
            while( !arthmeticStack.empty() )
                variableStack.push( factory::create_arthmetic( get( arthmeticStack ), get( variableStack ), get( variableStack ) ) );
            return ::std::move( variableStack.top() );
        }else{
            while( ! arthmeticStack.empty()
            &&       arthmetic_priority_map[ _Char ]
                   < arthmetic_priority_map[ arthmeticStack.top() ] )
                variableStack.push( factory::create_arthmetic( get( arthmeticStack ), get( variableStack ), get( variableStack ) ) );
            arthmeticStack.push( _Char );
        }
    }
    
    while( !arthmeticStack.empty() )
        variableStack.push( factory::create_arthmetic( get( arthmeticStack ), get( variableStack ), get( variableStack ) ) );
    return ::std::move( variableStack.top() );
}

int main( void ){
	::std::unordered_map< char, int > assign_map( { {'a',1},{'b',2},{'c',3} } );
	::std::string expr {"a+(a+b)*c"};
	::std::istringstream in( expr );
	abstr_expr_uptr exprTree =
		::std::move( analyse( in ) );
	::std::cout << expr << " = " << exprTree->interprete( assign_map );
	::std::endl( ::std::cout );
	return 0;
}

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值