我有一个如下的解析器代码,用于函数“TakeOne”。TakeOne 函数的工作方式就像它返回不等于 '%null%' 的第一个参数 例如:
TakeOne( %null% , '3', 'defaultVal'); --> result = 3
TakeOne( 5 , 'asd', 'defaultVal'); -> result = 5
现在我想将此功能修改为
TakeOne(parm1, parm2, ... , defaultValue);
是否可以在不使用 C++11 功能的情况下做到这一点?谢谢
#include <string>
#include <fstream>
#include <algorithm>
#include "sstream"
#include <locale.h>
#include <iomanip>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/functional/hash.hpp>
#include <boost/variant.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/algorithm/string.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef double NumValue;
typedef boost::variant<double, std::wstring> GenericValue;
const std::wstring ParserNullChar = L"%null%";
const double NumValueDoubleNull = std::numeric_limits<double>::infinity();
//Convert string to numeric values
struct AsNumValue : boost::static_visitor<double>
{
double operator()(double d) const { return d; }
double operator()(std::wstring const& s) const
{
if(boost::iequals(s, ParserNullChar))
{
return NumValueDoubleNull;
}
try { return boost::lexical_cast<double>(s); }
catch(...)
{
throw;
}
}
};
double Num(GenericValue const& val)
{
return boost::apply_visitor(AsNumValue(), val);
}
bool CheckIfNumValueIsNull(double num)
{
if(num == NumValueDoubleNull)
return true;
else
return false;
}
bool CheckIfGenericValIsNull(const GenericValue& val)
{
std::wostringstream woss;
woss << val;
if(boost::iequals(woss.str(), ParserNullChar))
{
return true;
}
else if(val.which() != 1 && CheckIfNumValueIsNull(Num(val)))
{
return true;
}
else
return false;
}
GenericValue TakeOne(GenericValue val1, GenericValue val2, GenericValue def)
{
if(!CheckIfGenericValIsNull(val1))
{
return val1;
}
else if(!CheckIfGenericValIsNull(val2))
{
return val2;
}
else
return def;
}
BOOST_PHOENIX_ADAPT_FUNCTION(GenericValue, TakeOne_, TakeOne, 3)
template <typename It, typename Skipper = qi::space_type >
struct MapFunctionParser : qi::grammar<It, GenericValue(), Skipper>
{
MapFunctionParser() : MapFunctionParser::base_type(expr_)
{
using namespace qi;
function_call_ =
(no_case[L"TakeOne"] > '(' > expr_ > ',' > expr_ > ',' > expr_ > ')')
[_val = TakeOne_(_1, _2, _3) ];
string_ = (L'"' > *~char_('"') > L'"')
| (L"'" > *~char_("'") > L"'");
factor_ =
(no_case[ParserNullChar]) [_val = NumValueDoubleNull]
| double_ [ _val = _1]
| string_ [ _val = _1]
| function_call_ [ _val = _1]
;
expr_ = factor_;
on_error<fail> ( expr_, std::cout
<< phx::val("Error! Expecting ") << _4 << phx::val(" here: \"")
<< phx::construct<std::string>(_3, _2) << phx::val("\"\n"));
#ifdef _DEBUG
BOOST_SPIRIT_DEBUG_NODE(function_call_);
BOOST_SPIRIT_DEBUG_NODE(expr_);
BOOST_SPIRIT_DEBUG_NODE(string_);
BOOST_SPIRIT_DEBUG_NODE(factor_);
#endif
}
private:
qi::rule<It, std::wstring()> string_;
qi::rule<It, GenericValue(), Skipper> function_call_, expr_, factor_;
};
int main()
{
std::wstringstream wss;
typedef std::wstring::const_iterator AttIter;
MapFunctionParser<AttIter , boost::spirit::qi::space_type> mapFunctionParser;
bool ret;
GenericValue result;
std::wstring functionStr = L"TakeOne(%null%, 5, 'default')";
std::wstring::const_iterator beginExpression(functionStr.begin());
std::wstring::const_iterator endExpression(functionStr.end());
ret = boost::spirit::qi::phrase_parse(beginExpression,endExpression,mapFunctionParser,boost::spirit::qi::space,result);
std::wcout << result << std::endl;
return 0;
}