Proto 表达式中某处的匹配运算符
Matching operator somewhere in Proto expression
为什么以下 Boost.Proto
语法不匹配取消引用运算符,这是什么
正确的做法?
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
struct has_deref : proto::or_<
proto::dereference<_>,
proto::nary_expr<_, proto::vararg<has_deref>>
>
{};
template<class Expr>
void test_expr(const Expr &e)
{
proto::display_expr(e);
std::cout << "matches? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
}
int main()
{
test_expr(proto::lit(1) + *proto::lit(2));
}
根据您的定义,您的 has_deref
语法匹配以下表达式:
- 应用于任何表达式的取消引用运算符
- ANY n-ary(可以是一元的,如:
complement
、negate
或 unary_plus
;二进制如:subscript
或 plus
;三元的like if_else_
, or directly n-ary like function
) 其参数递归匹配 has_deref
文法的表达式。
在您的示例中,您有一个 plus<terminal<int>,dereference<terminal<int> > >
,类似于 binary_expr<tag::plus,terminal<int>,unary_expr<tag::dereference,terminal<int> > >
。当试图匹配你的表达式时(我认为)Proto 首先尝试你的语法的第一个元素(dereference<_>
)并且显然失败了。然后尝试第二个 binary_expr<tag::plus,...>
匹配 nary_expr<_,...>
,因此它递归地尝试将语法与 plus
的两个参数表达式匹配。第二个直接匹配,但第一个(terminal<int>
)不匹配任何一种可能性,因此整个表达式无法匹配。
一种可能的(遗憾的是笨拙的)方法来做你想做的事情可能是这样的:
struct has_deref : proto::or_< //ignoring if_then_else and function
proto::dereference<_>,
proto::unary_expr<_, has_deref>,
proto::binary_expr<_, has_deref, _>,
proto::binary_expr<_, _, has_deref>
>
{};
匹配以下任一表达式:
- 应用于任何表达式的取消引用运算符。
- 应用于递归匹配
has_deref
的表达式的一元运算符。
- 一个二元运算符,其第一个操作数是匹配
has_deref
的表达式,第二个是 ANY 表达式(包括匹配 has_deref
的表达式)。
- 一个二元运算符,其第一个操作数是一个不匹配
has_deref
的表达式,第二个是一个匹配的表达式。
Here 是一个检查多个表达式是否匹配此新语法的示例(扩展为还检查最多有 2 个参数的函数):
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
template <typename Grammar>
struct function_contains_at_least_one : proto::or_<//this is awful, there should be a better way
proto::function<Grammar>,
proto::function<Grammar,_>,
proto::function<_,Grammar>,
proto::function<Grammar,_,_>,
proto::function<_,Grammar,_>,
proto::function<_,_,Grammar>
>
{};
struct has_deref : proto::or_< //ignoring if_else_
proto::dereference<_>,
proto::unary_expr<_,has_deref>,
proto::binary_expr<_, _,has_deref>,
proto::binary_expr<_,has_deref,_>,
function_contains_at_least_one<has_deref>
>
{};
template<class Expr>
void test_expr(const std::string& repr, const Expr &e)
{
std::cout << repr << " matches 'has_deref'? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
//display_expr(e);
}
#define TEST_EXPR( EXPR ) test_expr(#EXPR,EXPR)
int main()
{
using proto::lit;
TEST_EXPR(lit(1) + lit(2));
TEST_EXPR(lit(1) + *lit(2));
TEST_EXPR(*lit(1) + *lit(2));
TEST_EXPR(*(lit(1) * (lit("foo")+lit(2))));
TEST_EXPR(+-*lit(1)[~*lit(2)++]);
//testing functions
TEST_EXPR( lit(1)() );
TEST_EXPR( (*lit(1))() );
TEST_EXPR( lit(1)(lit(2)) );
TEST_EXPR( (*lit(1))(lit(2)) );
TEST_EXPR( lit(1)(*lit(2)) );
TEST_EXPR( lit(1)(lit(2),lit(3)) );
TEST_EXPR( (*lit(1))(*lit(2),*lit(3)) );
}
为什么以下 Boost.Proto
语法不匹配取消引用运算符,这是什么
正确的做法?
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
struct has_deref : proto::or_<
proto::dereference<_>,
proto::nary_expr<_, proto::vararg<has_deref>>
>
{};
template<class Expr>
void test_expr(const Expr &e)
{
proto::display_expr(e);
std::cout << "matches? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
}
int main()
{
test_expr(proto::lit(1) + *proto::lit(2));
}
根据您的定义,您的 has_deref
语法匹配以下表达式:
- 应用于任何表达式的取消引用运算符
- ANY n-ary(可以是一元的,如:
complement
、negate
或unary_plus
;二进制如:subscript
或plus
;三元的likeif_else_
, or directly n-ary likefunction
) 其参数递归匹配has_deref
文法的表达式。
在您的示例中,您有一个 plus<terminal<int>,dereference<terminal<int> > >
,类似于 binary_expr<tag::plus,terminal<int>,unary_expr<tag::dereference,terminal<int> > >
。当试图匹配你的表达式时(我认为)Proto 首先尝试你的语法的第一个元素(dereference<_>
)并且显然失败了。然后尝试第二个 binary_expr<tag::plus,...>
匹配 nary_expr<_,...>
,因此它递归地尝试将语法与 plus
的两个参数表达式匹配。第二个直接匹配,但第一个(terminal<int>
)不匹配任何一种可能性,因此整个表达式无法匹配。
一种可能的(遗憾的是笨拙的)方法来做你想做的事情可能是这样的:
struct has_deref : proto::or_< //ignoring if_then_else and function
proto::dereference<_>,
proto::unary_expr<_, has_deref>,
proto::binary_expr<_, has_deref, _>,
proto::binary_expr<_, _, has_deref>
>
{};
匹配以下任一表达式:
- 应用于任何表达式的取消引用运算符。
- 应用于递归匹配
has_deref
的表达式的一元运算符。 - 一个二元运算符,其第一个操作数是匹配
has_deref
的表达式,第二个是 ANY 表达式(包括匹配has_deref
的表达式)。 - 一个二元运算符,其第一个操作数是一个不匹配
has_deref
的表达式,第二个是一个匹配的表达式。
Here 是一个检查多个表达式是否匹配此新语法的示例(扩展为还检查最多有 2 个参数的函数):
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
using proto::_;
template <typename Grammar>
struct function_contains_at_least_one : proto::or_<//this is awful, there should be a better way
proto::function<Grammar>,
proto::function<Grammar,_>,
proto::function<_,Grammar>,
proto::function<Grammar,_,_>,
proto::function<_,Grammar,_>,
proto::function<_,_,Grammar>
>
{};
struct has_deref : proto::or_< //ignoring if_else_
proto::dereference<_>,
proto::unary_expr<_,has_deref>,
proto::binary_expr<_, _,has_deref>,
proto::binary_expr<_,has_deref,_>,
function_contains_at_least_one<has_deref>
>
{};
template<class Expr>
void test_expr(const std::string& repr, const Expr &e)
{
std::cout << repr << " matches 'has_deref'? " << std::boolalpha << proto::matches<Expr,
has_deref>::value << std::endl;
//display_expr(e);
}
#define TEST_EXPR( EXPR ) test_expr(#EXPR,EXPR)
int main()
{
using proto::lit;
TEST_EXPR(lit(1) + lit(2));
TEST_EXPR(lit(1) + *lit(2));
TEST_EXPR(*lit(1) + *lit(2));
TEST_EXPR(*(lit(1) * (lit("foo")+lit(2))));
TEST_EXPR(+-*lit(1)[~*lit(2)++]);
//testing functions
TEST_EXPR( lit(1)() );
TEST_EXPR( (*lit(1))() );
TEST_EXPR( lit(1)(lit(2)) );
TEST_EXPR( (*lit(1))(lit(2)) );
TEST_EXPR( lit(1)(*lit(2)) );
TEST_EXPR( lit(1)(lit(2),lit(3)) );
TEST_EXPR( (*lit(1))(*lit(2),*lit(3)) );
}