C++ 解析;“真的”;及;假;使用Boost.Spirit.Lex和Boost.Spirit.Qi

C++ 解析;“真的”;及;假;使用Boost.Spirit.Lex和Boost.Spirit.Qi,c++,parsing,boost-spirit,C++,Parsing,Boost Spirit,作为使用Boost.Spirit的大型语法的第一阶段,我试图解析“true”和“false”以生成相应的bool值,true和false 我正在使用Spirit.Lex来标记输入,并为整数和浮点文本(包括用宽松的科学符号表示的文本)提供一个有效的实现,公开int和float属性 令牌定义 #包括 名称空间lex=boost::spirit::lex; typedef boost::mpl::向量标记\值\类型; 模板 struct basic_literal_标记:lex::lexer{ 基本文

作为使用Boost.Spirit的大型语法的第一阶段,我试图解析“true”和“false”以生成相应的bool值,
true
false

我正在使用Spirit.Lex来标记输入,并为整数和浮点文本(包括用宽松的科学符号表示的文本)提供一个有效的实现,公开
int
float
属性

令牌定义
#包括
名称空间lex=boost::spirit::lex;
typedef boost::mpl::向量标记\值\类型;
模板
struct basic_literal_标记:lex::lexer{
基本文字符号({
这个->self.add_模式(“INT”,“[-+]?[0-9]+”);
int_literal=“{int}”;
//要以浮点形式进行词法分析,数值文字必须有小数点
//或者包含一个指数,否则它将被视为整数。
float_literal=“{INT}”((\\.[0-9]+)([eE]{INT})?)|([eE]{INT}));
literal_true=“true”;
literal_false=“false”;
这->self=literal|u true | literal|u false | float|u literal | int|u literal;
}
lex::token_def int_literal;
lex::token_def float_literal;
lex::token_def literal_true,literal_false;
};
测试浮点文本的解析 我的实际实现使用Boost.Test,但这是一个自包含的示例

#include <string>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <limits>

bool parse_and_check_float(std::string const & input, float expected) {
    typedef std::string::const_iterator base_iterator_type;
    typedef lex::lexertl::token<base_iterator_type,
                token_value_type
            > token_type;
    typedef lex::lexertl::lexer<token_type> lexer_type;

    basic_literal_tokens<lexer_type> basic_literal_lexer;
    base_iterator_type input_iter(input.begin());

    float actual;

    bool result = lex::tokenize_and_parse(input_iter, input.end(),
                                          basic_literal_lexer,
                                          basic_literal_lexer.float_literal,
                                          actual);
    return result && std::abs(expected - actual) < std::numeric_limits<float>::epsilon();
}

int main(int argc, char *argv[]) {
    if (parse_and_check_float("+31.4e-1", 3.14)) {
        return EXIT_SUCCESS;
    } else {
        return EXIT_FAILURE;
    }
}
#包括
#包括
#包括
#包括
#包括
bool parse_和check_float(标准::字符串常量和输入,应为float){
typedef std::string::const_iterator base_iterator_type;
typedef lex::lexertl::token token_type;
typedef lex::lexertl::lexer lexer_type;
基本文字符号基本文字符号;
基本迭代器类型输入iter(input.begin());
浮动实际值;
bool result=lex::tokenize_和_parse(input_iter,input.end(),
基本文字词汇器,
基本字面值字面值。浮点字面值,
实际的);
返回结果&std::abs(预期-实际)
解析“真”和“假” 我的问题是当试图解析“真”和“假”时。这是我正在使用的测试代码(在删除Boost.test部分之后):

bool解析和检查bool(标准::字符串常量和输入,预期bool){
typedef std::string::const_iterator base_iterator_type;
typedef lex::lexertl::token token_type;
typedef lex::lexertl::lexer lexer_type;
基本文字符号基本文字符号;
基本迭代器类型输入iter(input.begin());
布尔实际值;
lex::token_def parser=预期值?basic_literal_lexer.literal_true
:basic_literal_lexer.literal_false;
bool result=lex::tokenize_和_parse(input_iter,input.end(),
基本的文字分析器、语法分析器、,
实际的);
返回结果&&actual==预期结果;
}
但编译失败的原因是:

boost/spirit/home/qi/detail/assign_to.hpp: In function ‘void boost::spirit::traits::assign_to(const Iterator&, const Iterator&, Attribute&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Attribute = bool]’:
boost/spirit/home/lex/lexer/lexertl/token.hpp:434:   instantiated from ‘static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, boost::spirit::lex::lexertl::token<Iterator, AttributeTypes, HasState>, void>::call(const boost::spirit::lex::lexertl::token<Iterator, AttributeTypes, HasState>&, Attribute&) [with Attribute = bool, Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, AttributeTypes = boost::mpl::vector<int, float, bool, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, HasState = mpl_::bool_<true>]’

... backtrace of instantiation points ....

boost/spirit/home/qi/detail/assign_to.hpp:79: error: no matching function for call to ‘boost::spirit::traits::assign_to_attribute_from_iterators<bool, __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>::call(const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, bool&)’
boost/spirit/home/qi/detail/construct.hpp:64: note: candidates are: static void boost::spirit::traits::assign_to_attribute_from_iterators<bool, Iterator, void>::call(const Iterator&, const Iterator&, char&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]
boost/spirit/home/qi/detail/assign_to.hpp:在函数“void boost::spirit::traits::assign_to(const迭代器&,const迭代器&,Attribute&),[带迭代器=u gnu_cxx::u normal_迭代器,Attribute=bool]:
boost/spirit/home/lex/lexer/lexertl/token.hpp:434:从“static void boost::spirit::traits::assign_to_attribute_from_value::call(const boost::spirit::lex::lexertl::token&,attribute&)[with attribute=bool,Iterator=u gnu\u cxx::u normal_u迭代器,attributepes=boost::mpl::vector,HasState=mpl::bool]'
... 实例化点的回溯跟踪。。。。
boost/spirit/home/qi/detail/assign_to.hpp:79:错误:没有匹配函数用于调用来自迭代器::call的“boost::spirit::traits::assign_to_attribute_”(const u gnu_cxx::u normal_迭代器&,const u gnu cxx::u normal_u迭代器&,bool&)'
boost/spirit/home/qi/detail/construct.hpp:64:注意:候选对象是:静态void boost::spirit::traits::将_从_迭代器中分配给_属性_::call(const迭代器&,const迭代器&,char&)[带迭代器=u gnu_cxx:u normal u迭代器]

我对这一点的解释是精神。齐不知道如何将字符串转换为布尔-当然不是这样?以前有其他人这样做过吗?如果是这样的话,怎么办?

这实际上看起来像是Spirit 2.4.1中的一个bug,它已经在subversion中修复了。日志消息是“Spirit:Fixed cut&paste error,adding missing specialization for assign_to_attribute_from_iterators”。
(hkaiser于2010年11月18日签入r66624)。

您想要类似的内容吗

qi::rule<Iterator, bool> true_false_parser;
a = qi::lexeme[ qi::no_case[ qi::eps > ( qi::lit("true")[ _val=true] | qi::lit("false")[ _val=false] ) ] ];
qi::规则true\u false\u解析器;
a=qi::lexeme[qi::no_case[qi::eps>(qi::lit(“true”)[\uval=true]| qi::lit(“false”)[\uval=false])];
如果令牌不是“真”或“假”,则将抛出

默认为false do

qi::rule<Iterator, bool> true_false_parser;
a = qi::lexeme[ qi::no_case[ ( qi::lit("true")[ _val=true] ) | (*qi::char_)[_val=false] ] ];
qi::规则true\u false\u解析器;
a=qi::lexeme[qi::no_case[(qi::lit(“true”)[[u val=true]));(*qi::char][u val=false]];

您提供的代码可以使用Spirit V2.4.1(与oost V1.45一起发布)为我编译。您似乎遇到了一个bug,这个bug已经在最新版本中修复。

谢谢,但是您的解决方案不排除使用Spirit.Lex吗?您正在匹配文本字符串,但解析器将在标记上迭代。我相信使用lexeme可以解决这一问题。还有,IIRC,一个允许访问底层字符的qi::raw。我在Lex方面从来没有太多的运气,我更喜欢用Qi来做我的词法。公平地说,这看起来是一个纯粹用Qi来做的好方法(顺便说一句,这是我不接受你答案的唯一原因)。我会投票给你,但我是新来的,还没有代表。哈特穆特,你好,你是如何获得你的Spirit 2.4.1版本的?我已经查过了
qi::rule<Iterator, bool> true_false_parser;
a = qi::lexeme[ qi::no_case[ qi::eps > ( qi::lit("true")[ _val=true] | qi::lit("false")[ _val=false] ) ] ];
qi::rule<Iterator, bool> true_false_parser;
a = qi::lexeme[ qi::no_case[ ( qi::lit("true")[ _val=true] ) | (*qi::char_)[_val=false] ] ];