我是C ++的新手,但是我需要解析类似SQL的表达式: 国='美国' AND state =' CA' AND price> = 100.0,这只是一个假的例子,但它是可行的。
所以,我尝试用精神QI来解决。每列都有一个特定的类型:float,integer,double,char和string。我想创建一个可重用的语法来支持那些带有模板或/和特征的列类型,但是我被阻止了。
我想要这样的东西:
template <typename Iterator, typename ColumnType, typename Skipper>
struct test : qi::grammar<Iterator, ColumnType, Skipper>
{
test() : test::base_type(expression)
{
expression = MyTrait<ColumnType>::type >> "AND" >> MyTrait<ColumnType>::type;
}
qi::rule<Iterator, ColumnType, Skipper> expression;
};
我尝试使用Signature模板参数,但没有用。
MyTrait.h: 使用名称空间boost :: spirit :: qi;
template< typename T >
struct MyTrait
{
typedef T type;
};
template<> struct MyTrait< double >
{
typedef double_type type;
};
template<> struct MyTrait< float >
{
typedef float_type type;
};
MyTrait的基本思想是将原始类型(double,float ...)转换为精神QI类型,以便在语法中使用它们。请注意,MyTrait&lt; \ double&gt; :: type会从QI中生成double_type,但在语法中必须是double _。
main.cpp中:
int main() {
std::string input("99.0 AND 2.0");
std::string::const_iterator iter = input.begin();
std::string::const_iterator end = input.end();
test<std::string::const_iterator, double, qi::space_type> test_parser;
double result;
bool r = phrase_parse(iter, end, test_parser, qi::space, result);
return 0;
}
我是在正确的轨道上吗?
按照Chris Beck的要求遵循编译器错误消息:
g++-4.8 -I/usr/include/boost -O0 -g3 -Wall -c -fmessage-length=0 --std=c++11 -fpermissive -MMD -MP -MF"src/main.d" -MT"src/main.o" -o "src/main.o" "../src/main.cpp"
../src/main.cpp: In instantiation of ‘test<Iterator, ColumnType, Skipper>::test() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; ColumnType = double; Skipper = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0l>]’:
../src/main.cpp:91:60: required from here
../src/main.cpp:76:57: error: dependent-name ‘MyTrait<ColumnType>::type’ is parsed as a non-type, but instantiation yields a type
expression = MyTrait<ColumnType>::type >> "AND" >> MyTrait<ColumnType>::type;
^
../src/main.cpp:76:57: note: say ‘typename MyTrait<ColumnType>::type’ if a type is meant
../src/main.cpp:76:48: error: dependent-name ‘MyTrait<ColumnType>::type’ is parsed as a non-type, but instantiation yields a type
expression = MyTrait<ColumnType>::type >> "AND" >> MyTrait<ColumnType>::type;
^
../src/main.cpp:76:48: note: say ‘typename MyTrait<ColumnType>::type’ if a type is meant
答案 0 :(得分:0)
据我所知,您希望自动将特定解析器硬连线到给定的result_type。你这样做会放弃qi的灵活性。我建议您仔细检查您的方法。
下面的代码示例执行了我到目前为止所了解的内容。
但是(!)解析的实际结果不会是浮点数,而是一个矢量。输入字符串中有两个浮点数。其中一个迷路了。我没有采取任何措施阻止这种情况。
而且(!)下面的代码不会解决您可能要解析的不同类型(列)的混合和匹配问题。我没有采取任何措施使这成为可能。
以下代码只是明确地说明了您提供的输入。它编译,我希望这有助于攀登下一步。 ;)
#include <boost/spirit/home/qi.hpp>
#include <boost/utility/enable_if.hpp>
namespace qi = boost::spirit::qi;
template <typename T>
typename boost::enable_if<boost::is_same<T,double>, qi::double_type>::type
my_NOT_A_trait()
{
return qi::double_type();
};
template <typename T>
typename boost::enable_if<boost::is_same<T, float>, qi::float_type>::type
my_NOT_A_trait()
{
return qi::float_type();
};
template <typename Iterator, typename ColumnType>
struct test : qi::grammar<Iterator, ColumnType(), qi::space_type>
{
qi::rule<Iterator, ColumnType(), qi::space_type> expression;
test() : test::base_type(expression)
{
expression = my_NOT_A_trait<ColumnType>() >> qi::lit("AND") >> my_NOT_A_trait<ColumnType>();
}
};
template<typename Iterator, typename Skipper, typename Result>
bool parse(Iterator first, Iterator const& last, Skipper const& skipper, Result& result)
{
return qi::phrase_parse(first, last, test<Iterator,Result>(), qi::space, result);
}
int main()
{
float result;
std::string input = "99.0 AND 2.0";
auto b(input.begin()), e(input.end());
if (parse(b, e, qi::space, result))
std::cout << "Success." << std::endl;
else
std::cout << "Failure." << std::endl;
return 0;
}