1227 lines
23 KiB
Objective-C
1227 lines
23 KiB
Objective-C
#pragma once
|
|
|
|
// #2.1.2.12
|
|
//#include <string>
|
|
#include <map>
|
|
#include <deque>
|
|
#include <toolkit/khash.h>
|
|
#include "RefCounted.h"
|
|
#include "IntrusivePtr.h"
|
|
#include "TemplateUtil.h"
|
|
|
|
#include "float.h" /// 2011.04.15 - prodongi
|
|
|
|
namespace rp {
|
|
|
|
/// 2011.04.15 sprintf_s를 사용하면 반올림 되기 때문에 원하지 않는 텍스트가 뽑혀 진다, 그래서 수정함- prodongi
|
|
static std::string getRevisionFloat(float value, int point, std::string const& format)
|
|
{
|
|
static char buffer[256];
|
|
static float roundNumber[5] = { 1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f };
|
|
|
|
if (5 > point)
|
|
{
|
|
value *= roundNumber[point];
|
|
int _value = (int)value;
|
|
value = (float)_value/roundNumber[point];
|
|
}
|
|
|
|
::sprintf_s( buffer, format.c_str(), value);
|
|
return buffer;
|
|
}
|
|
|
|
// template namespace
|
|
template< typename NumericType >
|
|
struct expr {
|
|
|
|
typedef NumericType numeric_t;
|
|
|
|
template< typename Handler, typename Key >
|
|
class Parser
|
|
{
|
|
public:
|
|
enum MODE {
|
|
NORMAL,
|
|
ESCAPE,
|
|
};
|
|
Parser() : mMode( NORMAL ) {}
|
|
virtual ~Parser() {}
|
|
virtual void onNormal( const Key& expr ) = 0;
|
|
virtual void onEscape( const Key& escape ) = 0;
|
|
void call( const Key& expr )
|
|
{
|
|
Key target( expr );
|
|
target.erase( std::remove_if( target.begin(), target.end(), Remover() ), target.end() );
|
|
if( target.empty() )
|
|
return;
|
|
onNormal( target );
|
|
}
|
|
void compile( std::string::const_iterator begin, std::string::const_iterator end )
|
|
{
|
|
if( begin == end )
|
|
return;
|
|
|
|
std::string::const_iterator it = begin;
|
|
std::string::const_iterator token = begin;
|
|
|
|
typedef std::vector< std::pair< std::string::const_iterator, std::string::const_iterator > > Buffer;
|
|
Buffer buffer;
|
|
|
|
while( it != end )
|
|
{
|
|
static char escape;
|
|
|
|
switch( mMode )
|
|
{
|
|
case NORMAL:
|
|
{
|
|
if( std::binary_search( mTokens.begin(), mTokens.end(), *it ) )
|
|
{
|
|
if( token != it )
|
|
call( std::string( token, it ) );
|
|
call( std::string( it, it + 1 ) );
|
|
token = ++it;
|
|
continue;
|
|
}
|
|
else if( std::binary_search( mEscape.begin(), mEscape.end(), *it ) )
|
|
{
|
|
if( token != it )
|
|
call( std::string( token, it ) );
|
|
escape = *it;
|
|
token = ++it;
|
|
mMode = ESCAPE;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
case ESCAPE:
|
|
{
|
|
if( *it == escape )
|
|
{
|
|
if( token != it )
|
|
onEscape( std::string( token, it ) );
|
|
token = ++it;
|
|
mMode = NORMAL;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
if( token != end )
|
|
{
|
|
if( mMode == NORMAL )
|
|
call( std::string( token, end ) );
|
|
else
|
|
onEscape( std::string( token, end ) );
|
|
}
|
|
}
|
|
void addTokens( const char* token )
|
|
{
|
|
mTokens += token;
|
|
std::sort( mTokens.begin(), mTokens.end() );
|
|
}
|
|
void addEscape( const char* escape )
|
|
{
|
|
mEscape += escape;
|
|
std::sort( mEscape.begin(), mEscape.end() );
|
|
}
|
|
private:
|
|
typedef std::vector< std::pair< std::string::const_iterator, std::string::const_iterator > > Buffer;
|
|
|
|
struct Remover {
|
|
bool operator () ( const typename Key::value_type& elem ) {
|
|
if( elem == ' ' || elem == '\n' )
|
|
return true;
|
|
return false;
|
|
}
|
|
};
|
|
|
|
std::string mTokens;
|
|
std::string mEscape;
|
|
MODE mMode;
|
|
};
|
|
|
|
class IExpression;
|
|
typedef rp::intrusive_ptr< IExpression > IExpressionPtr;
|
|
|
|
class CallStack
|
|
{
|
|
typedef std::deque< IExpressionPtr > Chunk;
|
|
typedef std::deque< Chunk* > Stack;
|
|
|
|
public:
|
|
CallStack() : mChunk( 0 )
|
|
{
|
|
bindStack();
|
|
}
|
|
~CallStack()
|
|
{
|
|
while( !mStack.empty() )
|
|
{
|
|
Chunk* chunk = mStack.back();
|
|
delete chunk;
|
|
mStack.pop_back();
|
|
}
|
|
}
|
|
bool valid() const
|
|
{
|
|
return mChunk ? true : false;
|
|
}
|
|
bool empty() const
|
|
{
|
|
return valid() && mChunk->empty();
|
|
}
|
|
void bindStack()
|
|
{
|
|
mChunk = new Chunk();
|
|
mStack.push_back( mChunk );
|
|
}
|
|
void unbindStack()
|
|
{
|
|
if( mStack.empty() )
|
|
return;
|
|
|
|
Chunk* chunk = mStack.back();
|
|
delete chunk;
|
|
mStack.pop_back();
|
|
|
|
if( mStack.empty() )
|
|
mChunk = 0;
|
|
else
|
|
mChunk = mStack.back();
|
|
}
|
|
void push_back( IExpressionPtr expr )
|
|
{
|
|
mChunk->push_back( expr );
|
|
}
|
|
void pop_back()
|
|
{
|
|
mChunk->pop_back();
|
|
}
|
|
IExpressionPtr back()
|
|
{
|
|
return mChunk->back();
|
|
}
|
|
|
|
private:
|
|
Chunk* mChunk;
|
|
Stack mStack;
|
|
};
|
|
|
|
class IExpression : public rp::mixin::ref_counted
|
|
{
|
|
public:
|
|
virtual ~IExpression() {}
|
|
virtual IExpressionPtr create() = 0;
|
|
virtual void enter( CallStack& stack ) = 0;
|
|
virtual numeric_t toNumber() const = 0;
|
|
virtual std::string toString() const = 0;
|
|
virtual void push_back( IExpressionPtr expr ) = 0;
|
|
virtual void pop_back() = 0;
|
|
virtual IExpressionPtr back() = 0;
|
|
virtual bool empty() const = 0;
|
|
virtual bool isDelimiter() const { return false; }
|
|
};
|
|
|
|
class Expression : public IExpression
|
|
{
|
|
public:
|
|
virtual ~Expression() {}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
mArgs.push_back( expr );
|
|
}
|
|
virtual void pop_back()
|
|
{
|
|
mArgs.pop_back();
|
|
}
|
|
virtual IExpressionPtr back()
|
|
{
|
|
return mArgs.back();
|
|
}
|
|
virtual bool empty() const
|
|
{
|
|
return mArgs.empty();
|
|
}
|
|
|
|
protected:
|
|
void ftos( numeric_t src, std::string& dest ) const
|
|
{
|
|
char buf[ 256 ];
|
|
sprintf_s( buf, "%f", (float)src );
|
|
dest = buf;
|
|
}
|
|
void ntos( int src, std::string& dest ) const
|
|
{
|
|
char buf[ 256 ];
|
|
sprintf_s( buf, "%d", src );
|
|
dest = buf;
|
|
}
|
|
typedef std::deque< IExpressionPtr > ArgContainer;
|
|
ArgContainer mArgs;
|
|
};
|
|
|
|
/// 이항연산자
|
|
class Operator : public Expression
|
|
{
|
|
public:
|
|
virtual ~Operator() {}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
IExpressionPtr left = stack.back();
|
|
this->push_back( left );
|
|
|
|
stack.pop_back();
|
|
stack.push_back( this );
|
|
}
|
|
};
|
|
|
|
class Add : public Operator
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Add();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return add();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
std::string result;
|
|
ftos( add(), result );
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
numeric_t add() const
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 0 ]->toNumber() + mArgs[ 1 ]->toNumber();
|
|
return 0.f;
|
|
}
|
|
};
|
|
|
|
class Sub : public Operator
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Sub();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return sub();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
std::string result;
|
|
ftos( sub(), result );
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
numeric_t sub() const
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 0 ]->toNumber() - mArgs[ 1 ]->toNumber();
|
|
return 0.f;
|
|
}
|
|
};
|
|
|
|
class Mul : public Operator
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Mul();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return mul();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
std::string result;
|
|
ftos( mul(), result );
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
numeric_t mul() const
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
{
|
|
/// 2010.11.16 오차 때문에 0.0.000005f를 더함 - prodongi
|
|
//return mArgs[ 0 ]->toNumber() * mArgs[ 1 ]->toNumber();
|
|
numeric_t ret = mArgs[ 0 ]->toNumber() * mArgs[ 1 ]->toNumber();
|
|
return (ret <= 0.0f) ? ret : (ret + 0.000005f);
|
|
}
|
|
return 0.f;
|
|
}
|
|
};
|
|
|
|
class Div : public Operator
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Div();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return div();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
std::string result;
|
|
ftos( div(), result );
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
numeric_t div() const
|
|
{
|
|
if( mArgs.size() > 1 && mArgs[ 1 ]->toNumber() != 0.f )
|
|
return mArgs[ 0 ]->toNumber() / mArgs[ 1 ]->toNumber();
|
|
return 0.f;
|
|
}
|
|
};
|
|
|
|
/** @class Attach
|
|
@brief 사용: 표현식1 & 표현식2
|
|
@warning 설명: 표현식1 과 표현식2를 문자열로 치환하여 합친다.
|
|
*/
|
|
class Attach : public Operator
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Attach();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return (float)::atof( toString().c_str() );
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
std::string buffer;
|
|
|
|
for( ArgContainer::const_iterator it = mArgs.begin(); it != mArgs.end(); ++it )
|
|
buffer += (*it)->toString();
|
|
|
|
return buffer;
|
|
}
|
|
};
|
|
|
|
class OpenGroup : public Expression
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new OpenGroup();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
return "";
|
|
}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
stack.bindStack();
|
|
}
|
|
};
|
|
|
|
class CloseGroup : public Expression
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new CloseGroup();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return mArgs[ 0 ]->toNumber();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
return mArgs[ 0 ]->toString();
|
|
}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
while( !stack.empty() )
|
|
{
|
|
IExpressionPtr expr = stack.back();
|
|
stack.pop_back();
|
|
if( !expr->isDelimiter() )
|
|
this->push_back( expr );
|
|
}
|
|
|
|
stack.unbindStack();
|
|
|
|
if( !stack.valid() )
|
|
return;
|
|
|
|
if( stack.empty() || stack.back()->isDelimiter() )
|
|
{
|
|
stack.push_back( this );
|
|
}
|
|
else
|
|
{
|
|
IExpressionPtr expr = stack.back();
|
|
expr->push_back( this );
|
|
|
|
//
|
|
// 함수일 경우 앞쪽에 이항연산자가 있는지 확인
|
|
//
|
|
if( dynamic_cast< Function* >( expr.get() ) )
|
|
{
|
|
stack.pop_back();
|
|
|
|
if( !stack.empty() && dynamic_cast< Operator* >( stack.back().get() ) )
|
|
stack.back()->push_back( expr );
|
|
else
|
|
stack.push_back( expr );
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
class Delimiter : public Expression
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Delimiter();
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
return "";
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
assert( 0 );
|
|
}
|
|
virtual bool isDelimiter() const
|
|
{
|
|
return true;
|
|
}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
stack.push_back( this );
|
|
}
|
|
};
|
|
|
|
//
|
|
// 함수
|
|
//
|
|
|
|
class Function : public Expression
|
|
{
|
|
public:
|
|
virtual ~Function() {}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
stack.push_back( this );
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class If
|
|
@brief 사용: if( 표현식1, 표현식2, 표현식3 )
|
|
@warning 설명: 표현식1 이 0 이 아닐때 표현식2 를 사용, 표현식1 이 0 이면 표현식3 을 사용한다.
|
|
*/
|
|
class If : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new If();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
if( mArgs[ 0 ]->toNumber() )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toNumber();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toNumber();
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
if( mArgs[ 0 ]->toNumber() )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toString();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toString();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class If
|
|
@brief 사용: if( 표현식1, 표현식2, 표현식3 )
|
|
@warning 설명: 표현식1 이 0보다 크면표현식2 를 사용, 표현식1 이 0 이거나 작으면 표현식3 을 사용한다.
|
|
*/
|
|
class UnSignedIf : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new UnSignedIf();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
if( mArgs[ 0 ]->toNumber() > (numeric_t)(0) )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toNumber();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toNumber();
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
/// 2011.03.08 양수만 가능하도록 한다 - prodongi
|
|
if( mArgs[ 0 ]->toNumber() > (numeric_t)(0) )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toString();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toString();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
};
|
|
|
|
/// 2011.03.22 - prodongi
|
|
/**
|
|
@class SignedIf
|
|
@brief 사용: if( 표현식1, 표현식2, 표현식3 )
|
|
@warning 설명: 기존의 If()는 0일 때와 이닐때를 체크 하는데, SignedIf()는 0보다 작을 때와, 0과 같거나 클 때를 체크 함
|
|
*/
|
|
class SignedIf : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new SignedIf();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
if( mArgs[ 0 ]->toNumber() >= 0 )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toNumber();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toNumber();
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
if( mArgs[ 0 ]->toNumber() >= (numeric_t)(0) )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toString();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toString();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
};
|
|
|
|
/// 2011.04.13 - prodongi
|
|
/**
|
|
@class SignedIf
|
|
@brief 사용: if( 표현식1, 표현식2, 표현식3 )
|
|
@warning 설명: 기존의 If()는 0일 때와 이닐때를 체크 하는데, SignedIf()는 1보다 작을 때와, 1과 같거나 클 때를 체크 함
|
|
*/
|
|
class OneSignedIf : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new OneSignedIf();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
if( mArgs[ 0 ]->toNumber() >= 1 )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toNumber();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toNumber();
|
|
}
|
|
|
|
return 0.f;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
if( mArgs[ 0 ]->toNumber() >= (numeric_t)(1) )
|
|
{
|
|
if( mArgs.size() > 1 )
|
|
return mArgs[ 1 ]->toString();
|
|
}
|
|
else
|
|
{
|
|
if( mArgs.size() > 2 )
|
|
return mArgs[ 2 ]->toString();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class Int
|
|
@brief 사용: int( 숫자 )
|
|
@warning 설명: 숫자를 정수형으로 바꿔준다.
|
|
*/
|
|
class Int : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Int();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return mArgs[ 0 ]->toNumber();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
int number = (int)mArgs[ 0 ]->toNumber();
|
|
std::string dest;
|
|
ntos( number, dest );
|
|
return dest;
|
|
}
|
|
};
|
|
|
|
/// 2011.03.17 - prodongi
|
|
class SignedInt : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new SignedInt();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return mArgs[ 0 ]->toNumber();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
int number = (int)mArgs[ 0 ]->toNumber();
|
|
std::string strNum;
|
|
ntos( number, strNum );
|
|
|
|
std::string strSign;
|
|
if (0 < number) strSign = "+";
|
|
|
|
std::string strRet = strSign + strNum;
|
|
return strRet;
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class Int
|
|
@brief 사용: int( 숫자 )
|
|
@warning 설명: 숫자를 0보다 큰 정수형으로 바꿔준다.
|
|
*/
|
|
/// 2011.04.22 - prodongi
|
|
class AbsInt : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new AbsInt();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return abs((int)mArgs[ 0 ]->toNumber());
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
int number = abs((int)mArgs[ 0 ]->toNumber());
|
|
std::string dest;
|
|
ntos( number, dest );
|
|
return dest;
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class Float
|
|
@brief 사용: float( 숫자, 소수점자리수 )
|
|
@warning 설명: 소수점 자리수를 지정하지 않으면 기본적으로 4자리수까지 표현한다.
|
|
*/
|
|
class Float : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new Float();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return mArgs[ 0 ]->toNumber();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
numeric_t number = mArgs[ 0 ]->toNumber();
|
|
int floatingPoint = 4;
|
|
if( mArgs.size() > 1 )
|
|
floatingPoint = (int)mArgs[ 1 ]->toNumber();
|
|
|
|
std::string format;
|
|
ntos( floatingPoint, format );
|
|
|
|
format = "%." + format;
|
|
format += "f";
|
|
|
|
/// 2011.04.15 오차와 반올림 보정 - prodongi
|
|
/*
|
|
char buffer[ 256 ];
|
|
::sprintf_s( buffer, format.c_str(), (float)number );
|
|
|
|
return buffer;
|
|
*/
|
|
return getRevisionFloat(number, floatingPoint, format);
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class Float
|
|
@brief 사용: float( 숫자, 소수점자리수 )
|
|
@warning 설명: 소수점 자리수를 지정하지 않으면 기본적으로 4자리수까지 표현한다.양의 실수 표시
|
|
*/
|
|
class AbsFloat : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new AbsFloat();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return fabs(mArgs[ 0 ]->toNumber());
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
numeric_t number = fabs(mArgs[ 0 ]->toNumber());
|
|
int floatingPoint = 4;
|
|
if( mArgs.size() > 1 )
|
|
floatingPoint = (int)mArgs[ 1 ]->toNumber();
|
|
|
|
std::string format;
|
|
ntos( floatingPoint, format );
|
|
|
|
format = "%." + format;
|
|
format += "f";
|
|
|
|
/// 2011.04.15 오차와 반올림 보정 - prodongi
|
|
/*
|
|
char buffer[ 256 ];
|
|
::sprintf_s( buffer, format.c_str(), (float)number );
|
|
|
|
return buffer;
|
|
*/
|
|
return getRevisionFloat(number, floatingPoint, format);
|
|
}
|
|
};
|
|
|
|
/**
|
|
@class Float
|
|
@brief 사용: float( 숫자, 소수점자리수 )
|
|
@warning 설명: 소수점 자리수를 지정하지 않으면 기본적으로 4자리수까지 표현한다., +/- 표시
|
|
*/
|
|
class SignedFloat : public Function
|
|
{
|
|
public:
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return new SignedFloat();
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
while( !expr->empty() )
|
|
{
|
|
IExpressionPtr arg = expr->back();
|
|
expr->pop_back();
|
|
mArgs.push_back( arg );
|
|
}
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return 0.f;
|
|
|
|
return mArgs[ 0 ]->toNumber();
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
if( mArgs.empty() )
|
|
return "";
|
|
|
|
numeric_t number = mArgs[ 0 ]->toNumber();
|
|
int floatingPoint = 4;
|
|
if( mArgs.size() > 1 )
|
|
floatingPoint = (int)mArgs[ 1 ]->toNumber();
|
|
|
|
std::string format;
|
|
ntos( floatingPoint, format );
|
|
|
|
format = "%." + format;
|
|
format += "f";
|
|
|
|
if (0 < number)
|
|
{
|
|
format = "+" + format;
|
|
}
|
|
|
|
/// 2011.04.15 오차와 반올림 보정 - prodongi
|
|
/*
|
|
char buffer[ 256 ];
|
|
::sprintf_s( buffer, format.c_str(), (float)number );
|
|
|
|
return buffer;
|
|
*/
|
|
return getRevisionFloat(number, floatingPoint, format);
|
|
}
|
|
};
|
|
|
|
/// 값
|
|
class Value : public IExpression
|
|
{
|
|
public:
|
|
virtual ~Value() {}
|
|
virtual IExpressionPtr create()
|
|
{
|
|
return this;
|
|
}
|
|
virtual void enter( CallStack& stack )
|
|
{
|
|
if( stack.empty() || stack.back()->isDelimiter() )
|
|
{
|
|
stack.push_back( this );
|
|
}
|
|
else
|
|
{
|
|
IExpressionPtr ex = stack.back();
|
|
ex->push_back( this );
|
|
}
|
|
}
|
|
virtual void push_back( IExpressionPtr expr )
|
|
{
|
|
assert( 0 || "value can't have expression" );
|
|
}
|
|
virtual void pop_back()
|
|
{
|
|
assert( 0 || "value can't have expression" );
|
|
}
|
|
virtual IExpressionPtr back()
|
|
{
|
|
assert( 0 || "value can't have expression" );
|
|
return IExpressionPtr();
|
|
}
|
|
virtual bool empty() const
|
|
{
|
|
assert( 0 || "value can't have expression" );
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class Numeric : public Value
|
|
{
|
|
public:
|
|
virtual ~Numeric() {}
|
|
Numeric( numeric_t value ) : Value(), mValue( value )
|
|
{
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return mValue;
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
char temp[ 128 ];
|
|
sprintf_s( temp, "%f", (float)mValue );
|
|
return std::string( temp );
|
|
}
|
|
|
|
protected:
|
|
numeric_t mValue;
|
|
};
|
|
|
|
class String : public Value
|
|
{
|
|
public:
|
|
virtual ~String() {}
|
|
String( const char* value ) : Value(), mValue( value )
|
|
{
|
|
}
|
|
virtual numeric_t toNumber() const
|
|
{
|
|
return (float)::atof( mValue.c_str() );
|
|
}
|
|
virtual std::string toString() const
|
|
{
|
|
return mValue;
|
|
}
|
|
|
|
protected:
|
|
std::string mValue;
|
|
};
|
|
|
|
/// Factory
|
|
class Factory
|
|
{
|
|
public:
|
|
virtual ~Factory()
|
|
{
|
|
mEqDatas.clear();
|
|
}
|
|
void appendExpression( const char* key, IExpressionPtr value )
|
|
{
|
|
mEqDatas.add( key, value );
|
|
}
|
|
IExpressionPtr findExpression( const char* key )
|
|
{
|
|
IExpressionPtr metaEq;
|
|
if( mEqDatas.lookup( key, metaEq ) )
|
|
return metaEq->create();
|
|
|
|
return 0;
|
|
}
|
|
|
|
private:
|
|
KHash< IExpressionPtr, hashPr_string > mEqDatas;
|
|
};
|
|
|
|
/// Compiler
|
|
class Compiler : public Parser< Compiler, std::string >
|
|
{
|
|
public:
|
|
Compiler( Factory& factory ) : mFactory( factory )
|
|
{
|
|
}
|
|
virtual ~Compiler()
|
|
{
|
|
}
|
|
IExpressionPtr result()
|
|
{
|
|
return mStack.valid() ? mStack.back() : 0;
|
|
}
|
|
void clear()
|
|
{
|
|
mStack.clear();
|
|
}
|
|
virtual void onNormal( const std::string& expr )
|
|
{
|
|
if( !mStack.valid() )
|
|
return;
|
|
IExpressionPtr def = mFactory.findExpression( expr.c_str() );
|
|
if( !def )
|
|
def = new Numeric( (float)::atof( expr.c_str() ) );
|
|
def->enter( mStack );
|
|
}
|
|
virtual void onEscape( const std::string& escape )
|
|
{
|
|
if( !mStack.valid() )
|
|
return;
|
|
IExpressionPtr value( new String( escape.c_str() ) );
|
|
value->enter( mStack );
|
|
}
|
|
|
|
private:
|
|
CallStack mStack;
|
|
Factory& mFactory;
|
|
};
|
|
|
|
}; // eq_expr< numeric_t >
|
|
|
|
} // rp |