gpt4 book ai didi

c++ - Boost::spirit 如何解析和调用c++类函数表达式

转载 作者:太空狗 更新时间:2023-10-29 23:26:30 24 4
gpt4 key购买 nike

我想用boost spirit来解析像

这样的表达式

function1(arg1, arg2, function2(arg1, arg2, arg3), function3(arg1,arg2))

并调用相应的c++函数。解析上述表达式并通过 phoneix::bind() 调用相应的 c++ 函数的语法应该是什么?

我有两种类型的函数要调用

1) 字符串函数;

wstring GetSubString(wstring stringToCut, int position, int length); wstring GetStringToken(wstring stringToTokenize, wstring seperators, int tokenNumber );

2) 返回整数的函数;

int GetCount();

int GetId(wstring srcId, wstring srcType);

最佳答案

第二个答案(更务实)

这是第二次拍摄,用于比较:

以防万一您真的不想解析为抽象语法树表示,而是在解析期间即时评估函数,您可以简化语法。

它有 92 行,而不是第一个答案中的 209 行。这实际上取决于您要实现的内容,哪种方法更合适。

这种较短的方法有一些缺点:

  • 不太灵活(不可重复使用)
  • 不太健壮(如果函数有副作用,即使中途解析失败也会发生)
  • 可扩展性较差(支持的功能硬连线到语法1)

完整代码:

//#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/phoenix/function.hpp>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

typedef boost::variant<int, std::string> value;

//////////////////////////////////////////////////
// Demo functions:
value AnswerToLTUAE() {
return 42;
}

value ReverseString(value const& input) {
auto& as_string = boost::get<std::string>(input);
return std::string(as_string.rbegin(), as_string.rend());
}

value Concatenate(value const& a, value const& b) {
std::ostringstream oss;
oss << a << b;
return oss.str();
}

BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(value, AnswerToLTUAE_, AnswerToLTUAE)
BOOST_PHOENIX_ADAPT_FUNCTION(value, ReverseString_, ReverseString, 1)
BOOST_PHOENIX_ADAPT_FUNCTION(value, Concatenate_, Concatenate, 2)

//////////////////////////////////////////////////
// Parser grammar
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, value(), Skipper>
{
parser() : parser::base_type(expr_)
{
using namespace qi;

function_call_ =
(lit("AnswerToLTUAE") > '(' > ')')
[ _val = AnswerToLTUAE_() ]
| (lit("ReverseString") > '(' > expr_ > ')')
[ _val = ReverseString_(_1) ]
| (lit("Concatenate") > '(' > expr_ > ',' > expr_ > ')')
[ _val = Concatenate_(_1, _2) ]
;
string_ = as_string [
lexeme [ "'" >> *~char_("'") >> "'" ]
];
value_ = int_ | string_;

expr_ = function_call_ | value_;

on_error<fail> ( expr_, std::cout
<< phx::val("Error! Expecting ") << _4 << phx::val(" here: \"")
<< phx::construct<std::string>(_3, _2) << phx::val("\"\n"));

BOOST_SPIRIT_DEBUG_NODES((expr_)(function_call_)(value_)(string_))
}

private:
qi::rule<It, value(), Skipper> value_, function_call_, expr_, string_;
};

int main()
{
for (const std::string input: std::vector<std::string> {
"-99",
"'string'",
"AnswerToLTUAE()",
"ReverseString('string')",
"Concatenate('string', 987)",
"Concatenate('The Answer Is ', AnswerToLTUAE())",
})
{
auto f(std::begin(input)), l(std::end(input));
const static parser<decltype(f)> p;

value direct_eval;
bool ok = qi::phrase_parse(f,l,p,qi::space,direct_eval);

if (!ok)
std::cout << "invalid input\n";
else
{
std::cout << "input:\t" << input << "\n";
std::cout << "eval:\t" << direct_eval << "\n\n";
}

if (f!=l) std::cout << "unparsed: '" << std::string(f,l) << "'\n";
}
}

请注意,我们可以直接使用 boost::phoenix::bind 而不是使用 BOOST_PHOENIX_ADAPT_FUNCTION*。

输出还是一样:

input:  -99
eval: -99

input: 'string'
eval: string

input: AnswerToLTUAE()
eval: 42

input: ReverseString('string')
eval: gnirts

input: Concatenate('string', 987)
eval: string987

input: Concatenate('The Answer Is ', AnswerToLTUAE())
eval: The Answer Is 42

1 最后一个缺点很容易通过使用 'Nabialek Trick' 来弥补。

关于c++ - Boost::spirit 如何解析和调用c++类函数表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17012941/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com