Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用提升精神(qi)解析帝国价值观_C++_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 使用提升精神(qi)解析帝国价值观

C++ 使用提升精神(qi)解析帝国价值观,c++,boost-spirit,boost-spirit-qi,C++,Boost Spirit,Boost Spirit Qi,我是一个精神初学者 我想使用spirit将一个英制字符串值解析为一个结构 输入应接受以下语法: 5'3"1/2 5'1/2 3"1/2 我的伪语法非常简单,如下所示: myrule = ( ( (qi::uint_ >> L'\'') || (qi::uint_ >> L'"') ) >> -( qi::uint_ &g

我是一个精神初学者

我想使用spirit将一个英制字符串值解析为一个结构

输入应接受以下语法:

5'3"1/2 5'1/2 3"1/2 我的伪语法非常简单,如下所示:

myrule = (
    (
        (qi::uint_ >> L'\'')
        ||
        (qi::uint_ >> L'"') 
    ) 
    >> -(
            qi::uint_ 
            >> L'/' >> 
            qi::uint_
        )
    );
下面是我第一次尝试填充我的结构时非常幼稚的做法:

我在我的
STRUCT imp\u常量中添加了
BOOST\u FUSION\u ADAPT\u STRUCT
宏,然后尝试了以下语法:

qi::rule<std::string::const_iterator, imp_constant()> 
    impconst = qi::lexeme[ //not sure this is required since no skipper precised
        (
            (qi::uint_[phx::at_c<0>(qi::_val)=qi::_1] >> L'\'')
            ||
            (qi::uint_[phx::at_c<1>(qi::_val)=qi::_1] >> L'"') 
        ) 
        >> -(
            qi::uint_[phx::at_c<2>(qi::_val)=qi::_1] 
            >> L'/' >> 
            qi::uint_[phx::at_c<3>(qi::_val)=qi::_1]
            )
        ];
我想我不明白占位符在这种情况下的行为

因为我是精神世界的初学者,欢迎任何建议

多谢各位

这是完整的代码,这应该会有所帮助

#define BOOST_SPIRIT_DONT_USE_MPL_ASSERT_MSG 1
//#define BOOST_SPIRIT_DEBUG << uncomment to enable debug
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <boost/fusion/adapted.hpp>

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

struct imp_constant
{
    explicit imp_constant(unsigned int feet=0
                         ,unsigned int inch=0
                         ,unsigned int fracn=0
                         ,unsigned int fracd=1)
        :feet_(feet),inches_(inch),fracn_(fracn),fracd_(fracd){}
    unsigned int feet_,inches_,fracn_,fracd_;
};

std::ostream& operator<<(std::ostream& os, imp_constant const& cst)
{
    if (cst.feet_)
        os << cst.feet_ << '\''; 
    if (cst.inches_)    
        os << cst.inches_ << '"';
    if (cst.fracn_)
        os << cst.fracn_ << '/' << cst.fracd_;
    return os;
}

BOOST_FUSION_ADAPT_STRUCT(imp_constant, 
                          (unsigned int, feet_)
                          (unsigned int, inches_)
                          (unsigned int, fracn_)
                          (unsigned int, fracd_))

int _tmain(int argc, _TCHAR* argv[])
{
    std::string input;

    std::cout << "\n----------------------\n> ";
    while (std::getline(std::cin, input))
    {
        if (input.empty() || input[0] == 'q' || input[0] == 'Q')
            break;

        std::string::const_iterator f(input.begin()),l(input.end());
        try
        {
            imp_constant result;
            std::cout << "parsing: " << input << "\n";
            bool ok;


            qi::rule<std::string::const_iterator, imp_constant()> 
                impconst = qi::lexeme[ //not sure this is required since
                            //no skipper precised
                    (
                        (qi::uint_[phx::at_c<0>(qi::_val)=qi::_1]
                        >> L'\'')
                        ||
                        (qi::uint_[phx::at_c<1>(qi::_val)=qi::_1]
                        >> L'"') 
                        ) 
                        >> -(
                        qi::uint_[phx::at_c<2>(qi::_val)=qi::_1] 
                    >> L'/' >> 
                        qi::uint_[phx::at_c<3>(qi::_val)=qi::_1]
                    )
                ];

            ok=qi::phrase_parse(f,l,impconst ,qi::space,result);

            if (!ok)
                std::cerr << "invalid input\n";
            else
            {

                std::cout << "\n---------------------------\n";
                std::cout << "result="<< result;
            }
        } 
        catch (const qi::expectation_failure<const char *>& e)
        {
            std::cerr << "expect failure at '" 
                      << std::string(e.first, e.last) << "'\n";
        }
        catch (...)
        {
            std::cerr << "parse error\n";
        }
        if (f!=l) std::cerr << "unparsed: '" << std::string(f,l) << "'\n";
        std::cout << "\n-----------------------\n> ";
    }
    std::getchar();
    return 0;
}
\define BOOST\u SPIRIT\u not\u USE\u MPL\u ASSERT\u MSG 1

//#定义BOOST\u SPIRIT\u DEBUG您正在寻找的回溯

5'1/2
中的“1”首先被解析为潜在inches分支中的
qi::uint
,导致属性被分配

只有这样才会遇到“/”,这会导致从“英寸分支”回溯。但是属性已经设置好了。在这种情况下,显式默认值或
qi::hold
可以修复它

下面是我自己可能会说的话:

qi::rule<std::string::const_iterator, unsigned(char)> 
    component = qi::hold [ qi::uint_ >> qi::lit(qi::_r1) ];

qi::rule<std::string::const_iterator, imp_constant()> 
    impconst = 
        component(L'\'') ||
        component(L'"')  ||
        component(L'/')  ||
        qi::uint_
;

BOOST_SPIRIT_DEBUG_NODE(component);
BOOST_SPIRIT_DEBUG_NODE(impconst);

你正在寻找回溯

5'1/2
中的“1”首先被解析为潜在inches分支中的
qi::uint
,导致属性被分配

只有这样才会遇到“/”,这会导致从“英寸分支”回溯。但是属性已经设置好了。在这种情况下,显式默认值或
qi::hold
可以修复它

下面是我自己可能会说的话:

qi::rule<std::string::const_iterator, unsigned(char)> 
    component = qi::hold [ qi::uint_ >> qi::lit(qi::_r1) ];

qi::rule<std::string::const_iterator, imp_constant()> 
    impconst = 
        component(L'\'') ||
        component(L'"')  ||
        component(L'/')  ||
        qi::uint_
;

BOOST_SPIRIT_DEBUG_NODE(component);
BOOST_SPIRIT_DEBUG_NODE(impconst);

作为sehe答案的替代方案(您应该接受):

如果您将规则更改为:

qi::rule<std::string::const_iterator, imp_constant()> 
        impconst = 
                 (
                     (qi::uint_ >> L'\'')[phx::at_c<0>(qi::_val)=qi::_1]
                     ||
                     (qi::uint_ >> L'"')[phx::at_c<1>(qi::_val)=qi::_1]
                 )
                 >> 
                     -(qi::uint_ >> L'/' >> qi::uint_)
                     [phx::at_c<2>(qi::_val)=qi::_1,phx::at_c<3>(qi::_val)=qi::_2]
        ;
然后规则是:

qi::rule<std::string::const_iterator,unsigned int()> feet = (qi::uint_ >> L'\'') | qi::attr(0);
qi::rule<std::string::const_iterator,unsigned int()> inches = (qi::uint_ >> L'"') | qi::attr(0);
qi::rule<std::string::const_iterator,fraction()> fract = (qi::uint_ >> L'/' >> qi::uint_) | (qi::attr(0)>> qi::attr(1));
qi::rule<std::string::const_iterator, imp_constant()> impconst=feet>>inches>>fract;
qi::rule foots=(qi::uint\u>>L'\'')\124qi::attr(0);
qi::规则英寸=(qi::uint_>>L')| qi::属性(0);
qi::rule fract=(qi::uint_>>L'/'>>qi::uint_124;(qi::attr(0)>>qi::attr(1));
qi::规则impconst=英尺>>英寸>>分形;

.

作为sehe答案的替代方案(您应该接受):

如果您将规则更改为:

qi::rule<std::string::const_iterator, imp_constant()> 
        impconst = 
                 (
                     (qi::uint_ >> L'\'')[phx::at_c<0>(qi::_val)=qi::_1]
                     ||
                     (qi::uint_ >> L'"')[phx::at_c<1>(qi::_val)=qi::_1]
                 )
                 >> 
                     -(qi::uint_ >> L'/' >> qi::uint_)
                     [phx::at_c<2>(qi::_val)=qi::_1,phx::at_c<3>(qi::_val)=qi::_2]
        ;
然后规则是:

qi::rule<std::string::const_iterator,unsigned int()> feet = (qi::uint_ >> L'\'') | qi::attr(0);
qi::rule<std::string::const_iterator,unsigned int()> inches = (qi::uint_ >> L'"') | qi::attr(0);
qi::rule<std::string::const_iterator,fraction()> fract = (qi::uint_ >> L'/' >> qi::uint_) | (qi::attr(0)>> qi::attr(1));
qi::rule<std::string::const_iterator, imp_constant()> impconst=feet>>inches>>fract;
qi::rule foots=(qi::uint\u>>L'\'')\124qi::attr(0);
qi::规则英寸=(qi::uint_>>L')| qi::属性(0);
qi::rule fract=(qi::uint_>>L'/'>>qi::uint_124;(qi::attr(0)>>qi::attr(1));
qi::规则impconst=英尺>>英寸>>分形;

.

Hi sehe,首先,非常感谢您快速完整的回答(顺便说一句,感谢您在stackoverflow上发布的所有其他答案-我在阅读这些答案时学到了很多东西)。看起来确实不错。不幸的是,hold指令抱怨
无法从交换前后的“unsigned int”
推断boost::spirit::multi_pass的模板参数。用vs9和vs10测试过,知道吗?谢谢again@loic啊。我发现,对于clang/libc++,使用老凤凰代码的
qi::lazy
显然是不正确的(可能MSVC也是如此)。在all Include之前添加
#定义BOOST_SPIRIT_USE_PHOENIX_V3
#可以解决Clang的问题。我建议你加上它,看看它对你有什么好处。请参阅,您可以验证它是否适用于GCC和CLANGUN。幸运的是,它没有修复构建:
错误C2784:“无效boost::spirit::swap(boost::spirit::multi\u pass&,boost::spirit::multi\u pass&”):无法从“unsigned int”推断“boost::spirit::multi\u pass&”的模板参数。
。很遗憾无法测试你的解决方案,我发现你的解决方案比其他解决方案更干净。嗨,sehe,首先,非常感谢你快速完整的回答(顺便说一句,你在stackoverflow上发布的所有其他答案-我在阅读它们时学到了很多)。看起来确实不错。不幸的是,hold指令抱怨
无法从交换前后的“unsigned int”
推断boost::spirit::multi_pass的模板参数。用vs9和vs10测试过,知道吗?谢谢again@loic啊。我发现,对于clang/libc++,使用老凤凰代码的
qi::lazy
显然是不正确的(可能MSVC也是如此)。在all Include之前添加
#定义BOOST_SPIRIT_USE_PHOENIX_V3
#可以解决Clang的问题。我建议你加上它,看看它对你有什么好处。请参阅,您可以验证它是否适用于GCC和CLANGUN。幸运的是,它没有修复构建:
错误C2784:“无效boost::spirit::swap(boost::spirit::multi\u pass&,boost::spirit::multi\u pass&”):无法从“unsigned int”推断“boost::spirit::multi\u pass&”的模板参数。
。很遗憾无法测试您的解决方案,我发现它比其他解决方案更干净。非常感谢,它工作得很好!我会记住,
| qi::attr(…)
作为可选的默认值技巧。+1我也这么认为:)我接受了这个想法,但选择了与原始想法保持一致,并解释发生了什么。(@loic属性技巧实际上就是我用“显式默认值或qi::hold可以修复它”简要暗示的内容)@sehe,的确,user2266005找到的解决方案与我的非常接近!抱歉错过了“显式默认”的提示,几天前我发现了spirit(顺便说一句,我欢迎自己来到这个新世界:),尽管我已经读了很多关于它的书,但我仍然对一些概念感到不舒服!谢谢你们两位的帮助,你们在这里和其他许多岗位上的贡献使《勇气》对我更具吸引力。非常感谢,它工作得很好!我会记住,
| qi::attr(…)
作为可选的默认值技巧。+1我也这么认为:)我接受了这个想法,但选择了与原始想法保持一致,并解释发生了什么。(@loic属性技巧实际上就是我用“显式默认值或qi::hold可以修复它”简要暗示的内容)@sehe,的确,user2266005找到的解决方案与我的非常接近!抱歉错过了“显式默认”提示,几天前我发现了spirit(顺便说一句,我欢迎自己来这里)
qi::rule<std::string::const_iterator,unsigned int()> feet = (qi::uint_ >> L'\'') | qi::attr(0);
qi::rule<std::string::const_iterator,unsigned int()> inches = (qi::uint_ >> L'"') | qi::attr(0);
qi::rule<std::string::const_iterator,fraction()> fract = (qi::uint_ >> L'/' >> qi::uint_) | (qi::attr(0)>> qi::attr(1));
qi::rule<std::string::const_iterator, imp_constant()> impconst=feet>>inches>>fract;