어떤 언어에 대해 그언어의 문법을 위한 표현 수단을 정의하고, 그 표현 수단을 사용하여 해당 언어로 작성된 문장을 해성하는 해석기를 정의하는 패턴.
장점
- 문법을 변경 시키거나 확장 시키는 것이 쉽다.
- 클래스들의 구현형태가 서로 비슷하므로 클래스 구현이 쉽다.
단점
- 새로운 작업을 추가하려면 각 클래스 마다 새로문 멤버함수를 정의해야 한다.(기존 클래스를 수정해야하는 문제가 발생할 수 있다.)
정규적인 문법이 있다면 라이브러리 형태로 구현해 두고 사용하면 여러모로 편리함.
패턴마다 예제 소스를 어떻게 만들지 생각이 안 나긴 다 마찬가지지만 이번껀 책 예제 이외엔 도저히 떠오르지가 않는다.
그래서 이번엔 책 예제와 거의 똑같이 많들고 헝가리안 표기법 공부를 한다는 생각으로 작성했다.
/////////////////////////////////////////////////////////////////////////////////////
// 문자열 검색 트리
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class RegularExp
{
public:
virtual~RegularExp(){};
virtual bool Match( string szSrc ) = 0;
};
class CharacterExp : public RegularExp
{
string m_szLiteral;
public:
CharacterExp( const string i_str ) : m_szLiteral( i_str ){};
bool Match( string i_szSrc )
{
string::size_type pos = i_szSrc.find( m_szLiteral );
if( pos == string::npos )
return false;
return true;
}
~CharacterExp() {}
};
class OrExp : public RegularExp
{
RegularExp* m_pExp1;
RegularExp* m_pExp2;
public:
OrExp( RegularExp* pExp1 = NULL, RegularExp* pExp2 = NULL ) : m_pExp1( pExp1 ), m_pExp2( pExp2 ){};
bool Match(string szSrc)
{
return ( m_pExp1->Match( szSrc ) ) || ( m_pExp2->Match(szSrc) );
}
~OrExp()
{
if( m_pExp1 )
{
delete m_pExp1;
m_pExp1 = NULL;
}
if( m_pExp2 )
{
delete m_pExp2;
m_pExp2 = NULL;
}
}
};
class AndExp : public RegularExp
{
RegularExp* m_pExp1;
RegularExp* m_pExp2;
public:
AndExp( RegularExp* pExp1, RegularExp* pExp2 ) : m_pExp1( pExp1 ), m_pExp2( pExp2 ){};
bool Match( string i_szSrc )
{
return ( m_pExp1->Match(i_szSrc) ) && ( m_pExp2->Match(i_szSrc) );
}
~AndExp()
{
if( m_pExp1 )
{
delete m_pExp1;
m_pExp1 = NULL;
}
if( m_pExp2 )
{
delete m_pExp2;
m_pExp2 = NULL;
}
}
};
RegularExp* CreateRegularExp(string i_szSearchStr)
{
int iLen = i_szSearchStr.length();
int iPos = i_szSearchStr.find_first_of( "(&|" );
if( iPos >= ( iLen-1 ) )
{
return NULL;
}
if( i_szSearchStr[iPos] == '(' )
{
int iEndParenpos = 0;
int iParenCount = 1;
for (int i=iPos+1; i<iLen; i++)
{
if ( i_szSearchStr[i] == '(' ) iParenCount++;
else if( i_szSearchStr[i] == ')' ) iParenCount--;
else {}
if(iParenCount == 0)
{
int iNextPos = i_szSearchStr.find_first_of( "&|", i+1 );
if( iNextPos != -1 )
{
RegularExp* pExp1 = CreateRegularExp( i_szSearchStr.substr( iPos+1, i-iPos-1 ) );
RegularExp* pExp2 = CreateRegularExp( i_szSearchStr.substr( iNextPos+1, iLen-iNextPos-1 ) );
if( i_szSearchStr[iNextPos] == '&' )
{
return new AndExp(pExp1, pExp2);
}
else
{
return new OrExp(pExp1, pExp2);
}
}
else
return CreateRegularExp( i_szSearchStr.substr( iPos + 1, i- iPos - 1 ) );
}
}
// 수식 에러
return NULL;
}
else if( i_szSearchStr[iPos] == '&' )
{
RegularExp* pExp1 = CreateRegularExp( i_szSearchStr.substr( 0, iPos ) );
RegularExp* pExp2 = CreateRegularExp( i_szSearchStr.substr( iPos+1, iLen-iPos-1 ) );
return new AndExp(pExp1, pExp2);
}
else if( i_szSearchStr[iPos] == '|' )
{
RegularExp* pExp1 = CreateRegularExp( i_szSearchStr.substr( 0, iPos ) );
RegularExp* pExp2 = CreateRegularExp( i_szSearchStr.substr( iPos+1, iLen-iPos-1 ) );
return new OrExp(pExp1, pExp2);
}
else
{
return new CharacterExp( i_szSearchStr );
}
return NULL;
}
void main()
{
RegularExp* pRegExp = CreateRegularExp("하하&(이건|테스트)");
string szText = "이건 테스트 입니다. 하하";
if ( pRegExp->Match( szText ) )
{
//성공
int kkk = 0;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////




덧글