Boost::Spirit 表达式解析器,带有定义的函数
Posted
技术标签:
【中文标题】Boost::Spirit 表达式解析器,带有定义的函数【英文标题】:Boost::Spirit expression parser with defined functions 【发布时间】:2019-03-29 14:03:28 【问题描述】:我正在尝试解析一些表达式。我从llonesmiz 和Sehe 的令人印象深刻的答案开始
我想补充一些:
(1) 定义的参数。这些婴儿车由另一个班级作为地图提供。他们可能没有参数(整数)一或二:
imf ---> $imf imf(1) ---> $imf(1) imf(1,2) ---> $imf(1,2)我正在尝试获取参数名称“imf”,然后是它的参数(如果它们存在)(1),(2,2)......
(2) 由另一个类作为映射给出的定义函数。他们可能有一个、两个或三个参数:
cos(1) ---> cos(1) cross(imf(1),1) ---> cross($imf(1),1) fun3(1,2,1) ---> fun3(1,2,1)custom_fold_directive.hpp
namespace custom
namespace tag
struct fold BOOST_SPIRIT_IS_TAG() ;
template <typename Exposed, typename Expr>
boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>
fold(Expr const& expr)
return boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>(expr);
namespace boost namespace spirit
template <typename Expr, typename Exposed>
struct use_directive<qi::domain
, tag::stateful_tag<Expr, custom::tag::fold, Exposed> >
: mpl::true_ ;
namespace custom
template <typename Exposed, typename InitialParser, typename RepeatingParser>
struct fold_directive
fold_directive(InitialParser const& initial, RepeatingParser const& repeating):initial(initial),repeating(repeating)
template <typename Context, typename Iterator>
struct attribute
typedef typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type type;//This works in this case but is not generic
;
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper, Attribute& attr_) const
Iterator start = first;
typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type initial_attr;
if (!initial.parse(first, last, context, skipper, initial_attr))
first=start;
return false;
typename boost::spirit::traits::attribute_of<RepeatingParser,Context,Iterator>::type repeating_attr;
if(!repeating.parse(first, last, context, skipper, repeating_attr))
boost::spirit::traits::assign_to(initial_attr, attr_);
return true;
Exposed current_attr(initial_attr,repeating_attr);
while(repeating.parse(first, last, context, skipper, repeating_attr))
boost::spirit::traits::assign_to(Exposed(current_attr,repeating_attr),current_attr);
boost::spirit::traits::assign_to(current_attr,attr_);
return true;
template <typename Context>
boost::spirit::info what(Context& context) const
return boost::spirit::info("fold");
InitialParser initial;
RepeatingParser repeating;
;
namespace boost namespace spirit namespace qi
template <typename Expr, typename Exposed, typename Subject, typename Modifiers>
struct make_directive<
tag::stateful_tag<Expr, custom::tag::fold, Exposed>, Subject, Modifiers>
typedef custom::fold_directive<Exposed, Expr, Subject> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject, Modifiers const&) const
typedef tag::stateful_tag<
Expr, custom::tag::fold, Exposed> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term),subject);
;
main.cpp
//#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "custom_fold_directive.hpp"
namespace qi = boost::spirit::qi;
// DEFINING TYPES
struct op_not ;
struct op_or ;
struct op_and ;
struct op_equal ;
struct op_unequal ;
struct op_sum ;
struct op_difference ;
struct op_factor ;
struct op_division ;
struct op_component;
namespace Expression
typedef std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;
/*
* tree structure definition
*/
typedef boost::variant<var,
boost::recursive_wrapper<unop <op_not> >,
boost::recursive_wrapper<binop<op_equal> >,
boost::recursive_wrapper<binop<op_unequal> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_or> >,
boost::recursive_wrapper<binop<op_difference> >,
boost::recursive_wrapper<binop<op_sum> >,
boost::recursive_wrapper<binop<op_factor> >,
boost::recursive_wrapper<binop<op_division> >,
boost::recursive_wrapper<binop<op_component> >
> expressionContainer;
template <typename tag> struct binop
explicit binop(const expressionContainer& l
, const expressionContainer& r)
: oper1(l), oper2(r)
expressionContainer oper1, oper2;
;
template <typename tag> struct comop
explicit comop(const expressionContainer& l
, const expressionContainer& r)
: oper1(l), oper2(r)
expressionContainer oper1, oper2;
;
template <typename tag> struct unop
explicit unop(const expressionContainer& o) : oper1(o)
expressionContainer oper1;
;
struct printer : boost::static_visitor<void>
printer(std::ostream& os) : _os(os)
std::ostream& _os;
//
void operator()(const var& v) const _os << v;
// Logical
void operator()(const binop<op_and>& b) const print(" & ", b.oper1, b.oper2);
void operator()(const binop<op_or >& b) const print(" || ", b.oper1, b.oper2);
void operator()(const binop<op_equal>& b) const print(" == ", b.oper1, b.oper2);
void operator()(const binop<op_unequal>& b) const print(" != ", b.oper1, b.oper2);
//Math operators
void operator()(const binop<op_difference>& b) const print("-", b.oper1, b.oper2);
void operator()(const binop<op_sum>& b) const print("+", b.oper1, b.oper2);
void operator()(const binop<op_factor>& b) const print("*", b.oper1, b.oper2);
void operator()(const binop<op_division>& b) const print("/", b.oper1, b.oper2);
void operator()(const binop<op_component>& b) const print(",", b.oper1, b.oper2);
//unique operators
void operator()(const unop<op_not>& u) constprintUnique("!",u.oper1);
//Printer
void print(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
_os << "(";
boost::apply_visitor(*this, l);
_os << op;
boost::apply_visitor(*this, r);
_os << ")";
void printUnique(const std::string& op, const expressionContainer& l) const
_os << op;
boost::apply_visitor(*this, l);
void printPower(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
boost::apply_visitor(*this, l);
_os << op;
boost::apply_visitor(*this, r);
void printOutSide(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
_os << op;
_os << "(";
boost::apply_visitor(*this, l);
_os << ",";
boost::apply_visitor(*this, r);
_os << ")";
/**
* void printConst( const expressionContainer& l) const
std::map<std::string, std::string> consts;
consts["@pi"] = "3.14";
consts["@ro"]="1.5";
std::string key="@"+l.
boost::apply_visitor(*this, consts(key));
* @param l
*/
;
std::ostream& operator<<(std::ostream& os, const expressionContainer& e)
boost::apply_visitor(printer(os), e); return os;
/*
* EXPRESSION PARSER DEFINITION
*/
template <typename It, typename Skipper = boost::spirit::standard_wide::space_type>
struct parserExpression : qi::grammar<It, Expression::expressionContainer(), Skipper>
parserExpression() : parserExpression::base_type(expr_)
using namespace qi;
using namespace Expression;
using custom::fold;
expr_ = or_.alias();
// Logical Operators
or_ = fold<binop<op_or> >(and_.alias())[orOperator_ >> and_];
and_ = fold<binop<op_and> >(equal_.alias())[andOperator_ >> equal_];
equal_ = fold<binop<op_equal> >(unequal_.alias())[equalOperator_ >> unequal_];
unequal_ = fold<binop<op_unequal> >(sum_.alias())[unequalOperator_ >>sum_];
// Numerical Operators
sum_ = fold<binop<op_sum> >(difference_.alias())[sumOperator_ >> difference_];
difference_ = fold<binop<op_difference> >(factor_.alias())[differenceOperator_ >> factor_];
factor_ = fold<binop<op_factor> >(division_.alias())[factorOperator_ >> division_];
division_ = fold<binop<op_division> >(not_.alias())[divisionOperator_ >> not_];
// UNARY OPERATION
not_ = (notOperator_ > param_) [_val = boost::phoenix::construct<Expression::unop <op_not>>(_1)] | param_[_val=_1];
param_ = (definedParams ) [_val =_1] | component_[_val = _1];
component_=definedParams >> '(' >> args_[_val=_1] >>')'| simple[_val = _1];
simple = (('(' > expr_ > ')') | var_);
var_ %= qi::raw[+qi::double_];
args_%=qi::raw[+qi::int_ % ','];
notOperator_ = qi::char_('!');
andOperator_ = qi::string("&&");
orOperator_ = qi::string("||");
xorOperator_ = qi::char_("^");
equalOperator_ = qi::string("==");
unequalOperator_ = qi::string("!=");
sumOperator_ = qi::char_("+");
differenceOperator_ = qi::char_("-");
factorOperator_ = qi::char_("*");
divisionOperator_ = qi::char_("/");
greaterOperator_ = qi::char_(">");
greaterOrEqualOperator_ = qi::string(">=");
lowerOrEqualOperator_ = qi::string("<=");
lowerOperator_ = qi::char_("<");
componentOperator_=qi::char_(",");
// Defined Function
std::map<std::string, std::string> functions;
functions["fun1"] = "cos";
functions["fun2"] = "sin";
for(auto const&x:functions)
definedFunctions.add (x.first, x.second) ;
//defined parameters
std::map<std::string, std::string> paramsList;
paramsList["imf"] = "imf";
paramsList["spect"] = "spectro";
for(auto const&x:paramsList)
definedParams.add (x.first, x.second) ;
BOOST_SPIRIT_DEBUG_NODES((expr_)(or_)(xor_)(and_)(equal_)(unequal_)(greaterOrEqual_)(lowerOrEqual_)(lower_)(sum_)
(difference_)(factor_)(division_)(simple)(notOperator_)(andOperator_)(orOperator_)(xorOperator_)(equalOperator_)(unequalOperator_)
(sumOperator_)(differenceOperator_)(factorOperator_)(divisionOperator_)(greater_)(lower_));
private:
qi::rule<It, Expression::var(), Skipper> var_, args_;
qi::rule<It, Expression::expressionContainer(), Skipper> not_
, and_
, xor_
, or_
, equal_
, unequal_
, sum_
, difference_
, factor_
, division_
, simple
, expr_
,plusSign_
,minusSign_
,greater_
,greaterOrEqual_
,lowerOrEqual_
,lower_
,functions_
,param_
,component_;
qi::rule<It, Skipper> notOperator_
, andOperator_
, orOperator_
, xorOperator_
, equalOperator_
, unequalOperator_
, sumOperator_
, differenceOperator_
, factorOperator_
, divisionOperator_
, greaterOperator_
, greaterOrEqualOperator_
,lowerOrEqualOperator_
,lowerOperator_
,componentOperator_;
qi::symbols<char, std::string> definedFunctions;
qi::symbols<char, std::string> definedParams;
;
void parse(const std::string& str)
std::string::const_iterator iter = str.begin(), end = str.end();
parserExpression<std::string::const_iterator,qi::space_type> parser;
Expression::expressionContainer expr;
bool result = qi::phrase_parse(iter,end,parser,qi::space, expr);
if(result && iter==end)
std::cout << "Success." << std::endl;
std::cout << str << " => " << expr << std::endl;
else
std::cout << "Failure." << std::endl;
int main()
parse("imf");
parse("spect");
parse("imf(1)");
parse("spect(1,2)");
成功。 imf => imf 工作正常
成功。 spect => 光谱有效
imf(1) => 失败。预期 imf(1)
spect(1,2) => 失败。预期光谱(1,2)
【问题讨论】:
【参考方案1】:(1)
的输出不为空。它是 ASCII 0x01:
00000000: 2831 2920 3d3e 2001 0a (1) => ..
那是因为
var_ %= qi::lexeme[+qi::int_];
没有做你想做的事。它将1
解析为一个整数,然后将其放入char
的容器中(std::string 是一个容器)。简单解析一个数字,只解析int_
,把is当作一个字符串,考虑raw[]
:
var_ = qi::raw[qi::int_];
现在打印出来了:
Success.
(1) => 1
Success.
1+1 => (1+1)
关于其余部分,我完全不清楚您要如何解析事物。我怀疑你自己也不清楚:
一元运算符是一元,不是唯一的 一元运算符是运算符,而不是表达式子类型或标识符 如果你想让函数接受参数列表,为什么没有规则这样说 如果“definedParams”是参数 - 那和变量有什么区别?为了获得灵感,请查看这些已经使用参数进行解析器函数调用的答案:
Spirit qi parsing to an Abstract Syntax Tree for nested functions便于比较:Boost::spirit how to parse and call c++ function-like expressions 的此答案即时解释已解析的表达式(这模仿了在您自己的解析器中使用 [std::cout << "Parse multiplication: " << (qi::_1 * qi::_2)]
的方法)
那里的另一个答案 (Boost::spirit how to parse and call c++ function-like expressions) 实现了目标,但使用了专用的 AST 表示和单独的解释阶段。
稍微高级/相关:
也定义函数detecting function call with regex Implementing operator precedence with boost spirit 高级:How to provider user with autocomplete suggestions for given boost::spirit grammar?【讨论】:
+1 来自我,但这里不使用qi::int_
是一种邪恶吗?它会在不适合 int
的数字上失败,并且由于溢出/下溢检查,它会有点慢。
@NikitaKniazev 你的猜测和我的一样好。语法由OP提出。对我来说改变它似乎没有用。所以,这绝对不是“恶”。这似乎是一种代码气味。就像我说的,“我怀疑 [OP] 也不清楚” :)【参考方案2】:
根据 sehe 的建议,我添加了参数和函数的规则。对于函数,我根据参数的数量构建了 3 个列表“qi::symbols”。 解析器工作正常。
custom_fold_directive.hpp
namespace custom
namespace tag
struct fold BOOST_SPIRIT_IS_TAG() ;
template <typename Exposed, typename Expr>
boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>
fold(Expr const& expr)
return boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>(expr);
namespace boost namespace spirit
template <typename Expr, typename Exposed>
struct use_directive<qi::domain
, tag::stateful_tag<Expr, custom::tag::fold, Exposed> >
: mpl::true_ ;
namespace custom
template <typename Exposed, typename InitialParser, typename RepeatingParser>
struct fold_directive
fold_directive(InitialParser const& initial, RepeatingParser const& repeating):initial(initial),repeating(repeating)
template <typename Context, typename Iterator>
struct attribute
typedef typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type type;//This works in this case but is not generic
;
template <typename Iterator, typename Context
, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context& context, Skipper const& skipper, Attribute& attr_) const
Iterator start = first;
typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type initial_attr;
if (!initial.parse(first, last, context, skipper, initial_attr))
first=start;
return false;
typename boost::spirit::traits::attribute_of<RepeatingParser,Context,Iterator>::type repeating_attr;
if(!repeating.parse(first, last, context, skipper, repeating_attr))
boost::spirit::traits::assign_to(initial_attr, attr_);
return true;
Exposed current_attr(initial_attr,repeating_attr);
while(repeating.parse(first, last, context, skipper, repeating_attr))
boost::spirit::traits::assign_to(Exposed(current_attr,repeating_attr),current_attr);
boost::spirit::traits::assign_to(current_attr,attr_);
return true;
template <typename Context>
boost::spirit::info what(Context& context) const
return boost::spirit::info("fold");
InitialParser initial;
RepeatingParser repeating;
;
namespace boost namespace spirit namespace qi
template <typename Expr, typename Exposed, typename Subject, typename Modifiers>
struct make_directive<
tag::stateful_tag<Expr, custom::tag::fold, Exposed>, Subject, Modifiers>
typedef custom::fold_directive<Exposed, Expr, Subject> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject, Modifiers const&) const
typedef tag::stateful_tag<
Expr, custom::tag::fold, Exposed> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term),subject);
;
main.cpp
#include <boost/mpl/list.hpp>
//#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "custom_fold_directive.hpp"
namespace qi = boost::spirit::qi;
// Expression::triop <fun_generic>
// DEFINING TYPES
struct op_not ;
struct op_or ;
struct op_and ;
struct op_xor ;
struct op_equal ;
struct op_unequal ;
struct op_sum ;
struct op_difference ;
struct op_factor ;
struct op_division ;
struct op_power;
struct op_powerTen;
struct op_plusSign ;
struct op_minusSign ;
struct op_const ;
struct fun_three;
struct fun_two;
struct fun_one;
namespace Expression
typedef std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;
template <typename tag> struct triop;
template <typename tag> struct forop;
/*
* tree structure definition
*/
typedef boost::variant<var,
boost::recursive_wrapper<unop <op_not> >,
boost::recursive_wrapper<binop<op_equal> >,
boost::recursive_wrapper<binop<op_unequal> >,
boost::recursive_wrapper<binop<op_and> >,
boost::recursive_wrapper<binop<op_xor> >,
boost::recursive_wrapper<binop<op_or> >,
boost::recursive_wrapper<binop<op_difference> >,
boost::recursive_wrapper<binop<op_sum> >,
boost::recursive_wrapper<binop<op_factor> >,
boost::recursive_wrapper<binop<op_division> >,
boost::recursive_wrapper<binop<op_power> >,
boost::recursive_wrapper<binop<op_powerTen> >,
boost::recursive_wrapper<unop<op_minusSign> >,
boost::recursive_wrapper<unop<op_plusSign> >,
boost::recursive_wrapper<unop<op_const> >,
boost::recursive_wrapper<binop<fun_one> >,
boost::recursive_wrapper<triop<fun_two> >,
boost::recursive_wrapper<forop<fun_three> >
> expressionContainer;
template <typename tag> struct binop
explicit binop(const expressionContainer& l
, const expressionContainer& r)
: oper1(l), oper2(r)
expressionContainer oper1, oper2;
;
template <typename tag> struct unop
explicit unop(const expressionContainer& o) : oper1(o)
expressionContainer oper1;
;
template <typename tag> struct triop
explicit triop(const expressionContainer& functionId,
const expressionContainer& l
, const expressionContainer& r)
: oper1(functionId), oper2(l), oper3(r)
expressionContainer oper1, oper2, oper3;
;
template <typename tag> struct forop
explicit forop(const expressionContainer& functionId,
const expressionContainer& l,
const expressionContainer& m,
const expressionContainer& r)
: oper1(functionId), oper2(l), oper3(m),oper4(r)
expressionContainer oper1, oper2, oper3,oper4;
;
struct printer : boost::static_visitor<void>
printer(std::ostream& os) : _os(os)
std::ostream& _os;
void operator()(const var& v) const _os << v;
// Logical
void operator()(const binop<op_and>& b) const print(" & ", b.oper1, b.oper2);
void operator()(const binop<op_or >& b) const print(" || ", b.oper1, b.oper2);
void operator()(const binop<op_xor>& b) const print(" | ", b.oper1, b.oper2);
void operator()(const binop<op_equal>& b) const print(" == ", b.oper1, b.oper2);
void operator()(const binop<op_unequal>& b) const print(" != ", b.oper1, b.oper2);
//Math operators
void operator()(const binop<op_difference>& b) const print("-", b.oper1, b.oper2);
void operator()(const binop<op_sum>& b) const print("+", b.oper1, b.oper2);
void operator()(const binop<op_factor>& b) const print("*", b.oper1, b.oper2);
void operator()(const binop<op_division>& b) const print("/", b.oper1, b.oper2);
//Power Math operators
void operator()(const binop<op_power>& b) const print("pow", b.oper1, b.oper2);
void operator()(const binop<op_powerTen>& b) const printPower("e", b.oper1, b.oper2);
//unique operators
void operator()(const unop<op_not>& u) constprintUnique("!",u.oper1);
void operator()(const unop<op_plusSign>& u) constprintUnique("",u.oper1);
void operator()(const unop<op_minusSign>& u) constprintUnique("-",u.oper1);
void operator()(const unop<op_const>& u) constprintUnique("",u.oper1);
// print Functions
void operator()(const forop<fun_three>& b) const printFunctionThree(b.oper1, b.oper2, b.oper3, b.oper4);
void operator()(const triop<fun_two>& b) const printFunctionTwo(b.oper1, b.oper2, b.oper3);
void operator()(const binop<fun_one>& b) const printFunctionOne(b.oper1, b.oper2);
//Printer
void print(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
_os << "(";
boost::apply_visitor(*this, l);
_os << op;
boost::apply_visitor(*this, r);
_os << ")";
void printUnique(const std::string& op, const expressionContainer& l) const
_os << op;
boost::apply_visitor(*this, l);
void printPower(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
boost::apply_visitor(*this, l);
_os << op;
boost::apply_visitor(*this, r);
void printOutSide(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
_os << op;
_os << "(";
boost::apply_visitor(*this, l);
_os << ",";
boost::apply_visitor(*this, r);
_os << ")";
void printFunctionThree(const expressionContainer& functionId, const expressionContainer& l, const expressionContainer& m, const expressionContainer& r) const
boost::apply_visitor(*this, functionId);
_os << "(";
boost::apply_visitor(*this, l);
_os << ',';
boost::apply_visitor(*this, m);
_os << ',';
boost::apply_visitor(*this, r);
_os << ")";
void printFunctionTwo(const expressionContainer& functionId, const expressionContainer& l, const expressionContainer& r) const
boost::apply_visitor(*this, functionId);
_os << "(";
boost::apply_visitor(*this, l);
_os << ',';
boost::apply_visitor(*this, r);
_os << ")";
void printFunctionOne(const expressionContainer& functionId, const expressionContainer& l) const
boost::apply_visitor(*this, functionId);
_os << "(";
boost::apply_visitor(*this, l);
_os << ")";
;
std::ostream& operator<<(std::ostream& os, const expressionContainer& e)
boost::apply_visitor(printer(os), e); return os;
/*
* EXPRESSION PARSER DEFINITION
*/
template <typename It, typename Skipper = boost::spirit::standard_wide::space_type>
struct parserExpression : qi::grammar<It, Expression::expressionContainer(), Skipper>
parserExpression() : parserExpression::base_type(expr_)
using namespace qi;
using namespace Expression;
using custom::fold;
expr_ = or_.alias();
// Logical Operators
or_ = fold<binop<op_or> >(and_.alias())[orOperator_ >> and_];
and_ = fold<binop<op_and> >(equal_.alias())[andOperator_ >> equal_];
equal_ = fold<binop<op_equal> >(unequal_.alias())[equalOperator_ >> unequal_];
unequal_ = fold<binop<op_unequal> >(sum_.alias())[unequalOperator_ >>sum_];
// Numerical Operators
sum_ = fold<binop<op_sum> >(difference_.alias())[sumOperator_ >> difference_];
difference_ = fold<binop<op_difference> >(factor_.alias())[differenceOperator_ >> factor_];
factor_ = fold<binop<op_factor> >(division_.alias())[factorOperator_ >> division_];
division_ = fold<binop<op_division> >(functions_.alias())[divisionOperator_ >> functions_];
functions_ = (threeArgsFunction>>"(">>funArgs_>>componentOperator_>>funArgs_>>componentOperator_>>funArgs_>>")")[_val= boost::phoenix::construct<Expression::forop <fun_three>>(_1,_2,_3,_4)] ||
(twoArgsFunction>>"(">>funArgs_>>componentOperator_>>funArgs_>>")")[_val= boost::phoenix::construct<Expression::triop <fun_two>>(_1,_2,_3)]||
(oneArgsFunction>>"(">>funArgs_>>")")[_val= boost::phoenix::construct<Expression::binop <fun_one>>(_1,_2)]|not_[_val=_1];
// UNARY OPERATION
not_ = (notOperator_ > param_) [_val = boost::phoenix::construct<Expression::unop <op_not>>(_1)] | param_[_val=_1];
param_= (definedParams >>('(' >> (spectArgs_|vectorArgs_)>>')'))[_val='$'+_1+"("+qi::_2+")"] ||
definedParams[_val='$'+_1]| simple[_val = _1];
funArgs_=((expr_ |var_) |functions_);
simple = (('(' > expr_ > ')') | var_);
var_ = (+qi::char_('0','9') >> -qi::char_('.') >> -(+qi::char_('0','9'))) | ((qi::char_('.') >> +qi::char_('0','9')));
vectorArgs_%=qi::raw[qi::int_ > -(qi::char_(',')>>qi::int_) ];
spectArgs_ %=qi::raw[(qi::int_>>qi::char_(',')>>'*')|(qi::char_('*')>>qi::char_(',')>>qi::int_)];
notOperator_ = qi::char_('!');
andOperator_ = qi::string("&&");
orOperator_ = qi::string("||");
xorOperator_ = qi::char_("^");
equalOperator_ = qi::string("==");
unequalOperator_ = qi::string("!=");
sumOperator_ = qi::char_("+");
differenceOperator_ = qi::char_("-");
factorOperator_ = qi::char_("*");
divisionOperator_ = qi::char_("/");
greaterOperator_ = qi::char_(">");
greaterOrEqualOperator_ = qi::string(">=");
lowerOrEqualOperator_ = qi::string("<=");
lowerOperator_ = qi::char_("<");
componentOperator_=qi::char_(",");
// Defined Function
std::map<std::string, std::string> oneFunctions;
oneFunctions["fun1_1"] = "f11";
oneFunctions["fun1_2"] = "f12";
for(auto const&x:oneFunctions)
oneArgsFunction.add (x.first, x.second) ;
std::map<std::string, std::string> twoFunctions;
twoFunctions["fun2_1"] = "f21";
twoFunctions["fun2_2"] = "f22";
for(auto const&x:twoFunctions)
twoArgsFunction.add (x.first, x.second) ;
std::map<std::string, std::string> threeFunctions;
threeFunctions["fun3_1"] = "f31";
threeFunctions["fun3_2"] = "f32";
for(auto const&x:threeFunctions)
threeArgsFunction.add (x.first, x.second) ;
//defined parameters
std::map<std::string, std::string> paramsList;
paramsList["imf"] = "imf";
paramsList["param"] = "param";
for(auto const&x:paramsList)
definedParams.add (x.first, x.second) ;
BOOST_SPIRIT_DEBUG_NODES((expr_)(or_)(xor_)(and_)(equal_)(unequal_)(sum_)(difference_)(factor_)(division_)
(simple)(notOperator_)(andOperator_)(orOperator_)(xorOperator_)(equalOperator_)(unequalOperator_)
(sumOperator_)(differenceOperator_)(factorOperator_)(divisionOperator_)(functions_));
private:
qi::rule<It, Expression::var(), Skipper> var_, vectorArgs_, spectArgs_;
qi::rule<It, Expression::expressionContainer(), Skipper> not_
, and_
, xor_
, or_
, equal_
, unequal_
, sum_
, difference_
, factor_
, division_
, simple
, expr_
,plusSign_
,minusSign_
,greater_
,greaterOrEqual_
,lowerOrEqual_
,lower_
,functions_
,param_
,funArgs_;
qi::rule<It, Skipper> notOperator_
, andOperator_
, orOperator_
, xorOperator_
, equalOperator_
, unequalOperator_
, sumOperator_
, differenceOperator_
, factorOperator_
, divisionOperator_
, greaterOperator_
, greaterOrEqualOperator_
,lowerOrEqualOperator_
,lowerOperator_
,componentOperator_;
qi::symbols<char, std::string> twoArgsFunction;
qi::symbols<char, std::string> oneArgsFunction;
qi::symbols<char, std::string> threeArgsFunction;
qi::symbols<char, std::string> definedParams;
;
void parse(const std::string& str)
std::string::const_iterator iter = str.begin(), end = str.end();
parserExpression<std::string::const_iterator,qi::space_type> parser;
Expression::expressionContainer expr;
bool result = qi::phrase_parse(iter,end,parser,qi::space, expr);
if(result && iter==end)
std::cout << "Success." << std::endl;
std::cout << str << " => " << expr << std::endl;
else
std::cout << "Failure." << std::endl;
int main()
parse("1");
parse("1+1");
parse("(1+1)");
//
parse("fun1_1((1))");
//
parse("fun2_1(1,2)");
parse("fun2_1( (fun2_1(1,1)), (2))");
//
parse("fun3_1(fun1_1(1),fun2_1(2,3),imf(1,1))");
输出 成功。 1 => 1 成功。 国际货币基金组织 => 美元国际货币基金组织 成功。 imf(1) => $imf(1) 成功。 (1+1) => (1+1) 成功。 fun1_1((1)) => f11(1) 成功。 fun2_1(1,2) => f21(1,2) 成功。 fun2_1( (fun2_1(1,1)), (2)) => f21(f21(1,1),2) 成功。 fun3_1(fun1_1(1),fun2_1(2,3),imf(1,1)) => f31(f11(1),f21(2,3),$imf(1,1))
【讨论】:
以上是关于Boost::Spirit 表达式解析器,带有定义的函数的主要内容,如果未能解决你的问题,请参考以下文章
Boost Spirit x3 -- 使用其他解析器参数化解析器