- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在解析期间,我有一些属性只需要在语义操作中设置(因为它们是从正在解析的数据派生的,我想避免 global
变量和对 BOOST_FUSION_ADAPT_STRUCT< 的依赖
以及我的代码应该是通用的,以便我可以将它重用于多种类型)。如果我使用多个传递给 qi::phrase_parse
的变量,我会得到很长的编译错误列表。我非常需要帮助:-)
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
int main( int argc, char**argv )
{
bool rc;
std::string input("");
//Test case 1 works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
rc = qi::phrase_parse( iter, last, qi::eps[ qi::_val=11 ] ,
ascii::space, val1 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 << std::endl;
}
//Test case 2 does not compile
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
rc = qi::phrase_parse( iter, last,
qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ],
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
//Test case 3 works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
rc = qi::phrase_parse( iter, last,
qi::attr(1)>>qi::attr(2),
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
return 0;
}
我从 cv_and_he
中获取了“定制的”my_phrase_parse,但它破坏了我想要运行的完整测试用例的编译:
template<typename T,typename R>
void testParser( R rule )
{
for ( const auto input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" } )
{
bool rc;
T maxValue;
T minValue;
auto iter( input.begin() );
auto last( input.end() );
std::vector< T > v;
rc = my_phrase_parse( iter, last,
qi::eps[
ph::at_c<0>(qi::_val)=std::numeric_limits<T>::max(),
ph::at_c<1>(qi::_val)=std::numeric_limits<T>::min()
]
>> -( qi::omit[ qi::int_]
>> *rule[ ph::if_(ph::at_c<0>(qi::_val)>qi::_1)[ ph::at_c<0>(qi::_val)=qi::_1 ],
ph::if_(ph::at_c<1>(qi::_val)<qi::_1)[ ph::at_c<1>(qi::_val)=qi::_1 ]
] )
,ascii::space, minValue, maxValue,v ) && iter==last;
std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
if( rc )
{
std::cout << "min=" << minValue << " max=" << maxValue << "\t";
std::copy( v.begin(), v.end(), std::ostream_iterator<T>( std::cout," " ));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
...
testParser<double>( qi::double_ );
最佳答案
Phoenix placeholders that Spirit uses允许您从规则的上下文中操作重要信息。当您在调用 parse
或 phrase_parse
的表达式中直接使用它们时,没有规则,因此没有上下文。在版本 Boost 1.47.0 之前不起作用,并且为了使此行为一致,对这些函数的单参数版本应用了修复,但显然不适用于可变参数版本。
回避此问题的一种方法是创建一个规则,该规则具有一个 fusion::vector
属性,该规则引用了您在调用 phrase_parse
时使用的类型。
编辑:删除了“my_phrase_parse”,因为我不确定它是否正确
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
namespace fusion = boost::fusion;
int main( int argc, char**argv )
{
bool rc;
std::string input("");
//Test case works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
rc = qi::phrase_parse( iter, last, qi::eps[ qi::_val=11 ] ,
ascii::space, val1 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 << std::endl;
}
//You can use a rule
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
qi::rule<decltype(iter),fusion::vector<int&, int&>(),ascii::space_type> parser=qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ];
rc = qi::phrase_parse( iter, last,
parser,
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
return 0;
}
编辑 2:添加了另一种方法来解决您要在编辑中解决的问题
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi_core.hpp>
#include <boost/spirit/include/qi_omit.hpp>
#include <iostream>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename T>
struct min_max_set
{
min_max_set():min(std::numeric_limits<T>::max()),max(std::numeric_limits<T>::min()),set(){}
T min;
T max;
std::vector<T> set;
};
namespace boost{ namespace spirit { namespace traits
{
template <typename T>
struct is_container<min_max_set<T>>
: boost::mpl::true_
{};
template <typename T>
struct container_value<min_max_set<T>>
{
typedef T type;
};
template <typename T>
struct push_back_container<min_max_set<T>,T>
{
static bool call(min_max_set<T>& cont, const T& val)
{
if(cont.min>val)
cont.min=val;
if(cont.max<val)
cont.max=val;
cont.set.push_back(val);
return true;
}
};
}}}
template<typename T,typename R>
void testParser( R rule )
{
for ( const auto input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" } )
{
bool rc;
auto iter( input.begin() );
auto last( input.end() );
min_max_set<T> accum;
rc = qi::phrase_parse( iter, last,
qi::omit[qi::int_] >> *rule
,ascii::space, accum ) && iter==last;
std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
if( rc )
{
std::cout << "min=" << accum.min << " max=" << accum.max << "\t";
std::copy( accum.set.begin(), accum.set.end(), std::ostream_iterator<T>( std::cout," " ));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
int main( int argc, char**argv )
{
testParser<double>(qi::double_);
return 0;
}
关于c++ - 为传递到 qi::phrase_parse 的表达式设置语义 Action 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18429974/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!