Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.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
boost phoenix绑定具有多个参数和返回值的语义操作 我对C++和Boost精神都是新手。_Boost_Boost Spirit_Boost Bind_Boost Phoenix - Fatal编程技术网

boost phoenix绑定具有多个参数和返回值的语义操作 我对C++和Boost精神都是新手。

boost phoenix绑定具有多个参数和返回值的语义操作 我对C++和Boost精神都是新手。,boost,boost-spirit,boost-bind,boost-phoenix,Boost,Boost Spirit,Boost Bind,Boost Phoenix,这件事我已经坚持了一天了。 我想分析两个由点分隔的字符串。 基本上,我需要将以下字符串解析为整数 例如:[field]-->integer//working eg2:[instance.field]-->integer//不工作 对于第二个,我需要取两个字符串作为参数,对它们求值并返回相关的整数值。 我肯定错过了一件基本的事情,但我想不出来 请让我知道我的代码中的错误或更好的方法。 需要调用方法并获取值。我不能改变 这是和平的准则 #define BOOST_SPIRIT_USE_PHOENIX

这件事我已经坚持了一天了。 我想分析两个由点分隔的字符串。 基本上,我需要将以下字符串解析为整数

例如:[field]-->integer//working

eg2:[instance.field]-->integer//不工作

对于第二个,我需要取两个字符串作为参数,对它们求值并返回相关的整数值。

我肯定错过了一件基本的事情,但我想不出来

请让我知道我的代码中的错误或更好的方法。 需要调用方法并获取值。我不能改变

这是和平的准则

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_utree.hpp>

#include <iostream>
#include <string>


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


int fieldVal(std::vector<char> fieldName) { 
    std::string fieldValue(fieldName.begin(), fieldName.end());
    std::cout << "Field Name Recieved.::: " << fieldValue << std::endl;
    int i = 50; //just for test 
    return i;
}

int instanceFieldVal(std::string instance, std::string fieldName) {

    std::cout << "Recieved ::: " << instance <<" : "<< fieldName << std::endl;
    int i = 60; //just for test
    return i;
}

namespace client
{
    template <typename Iterator>
    struct calculator : qi::grammar<Iterator, ascii::space_type, int()>
    {
        calculator() : calculator::base_type(instanceFieldValue)
      /*change base type to "field" and comment everything relevant to 
        "instanceFieldValue", then it's working */

        {
            using qi::int_;
            using qi::_val;
            using qi::_1;
            using qi::char_;
            using qi::lexeme;

            field = lexeme[
                '['
                    >> +(~char_(".]["))
                    >> ']'
            ][qi::_val = phx::bind(&fieldVal, qi::_1)]; // this is working


            instanceField = '['
                    >> +(~char_(".]["))
                    >> '.'
                    >> +(~char_(".]["))
                    >> ']';

            instanceFieldValue 
                = instanceField[qi::_val = phx::bind(&instanceFieldVal, qi::_1)]; 
            // how ^this line should be changed??

        }

        qi::rule<Iterator, ascii::space_type, int()> field, instanceFieldValue;

        qi::rule<Iterator, ascii::space_type, std::string(), std::string()>instanceField;
    };
}


int main()
{

    std::cout << "Type an expression...or [q or Q] to quit\n\n";

    using boost::spirit::ascii::space;
    using boost::spirit::utree;
    typedef std::string::const_iterator iterator_type;
    typedef client::calculator<iterator_type> calculator;

    calculator calc; // Our grammar

    std::string str;
    while (std::getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        int val;
        bool r = phrase_parse(iter, end, calc, space, val);

        if (r && iter == end)
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded: " << val << "\n";
            std::cout << "-------------------------\n";
        }
        else
        {
            std::string rest(iter, end);
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "stopped at: \": " << rest << "\"\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}
#定义提升(精神)使用(凤凰)
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
名称空间spirit=boost::spirit;
名称空间phx=boost::phoenix;
int fieldVal(std::vector fieldName){
字符串字段值(fieldName.begin(),fieldName.end());
std::cout好吧,你说它是一个有多个参数的函数,但是你只传递一个参数:
\u 1

这怎么行?不行。这也是你想要传递的,因为第二个参数可能来自
instanceField
表达式,但第一个是…神奇的上下文

和往常一样,我会尽量减少状态和语义动作。事实上,我建议分离关注点:

  • 首先解析到
    std:vector
  • 成功解析后,对其进行评估
  • 这将导致一个类似于

    template <typename Iterator>
    struct path : qi::grammar<Iterator, std::deque<std::string>()> {
        path() : path::base_type(start) {
            using namespace qi;
    
            name          = +(graph - char_(".][")); // not matching spaces please
            qualifiedName = name % '.';
    
            start = skip(ascii::space) ['[' >> qualifiedName >> ']'];
    
            BOOST_SPIRIT_DEBUG_NODES((start)(qualifiedName)(name))
        }
    
      private:
        qi::rule<Iterator, std::deque<std::string>(), qi::ascii::space_type> qualifiedName;
        qi::rule<Iterator, std::string()> name;
        qi::rule<Iterator, std::deque<std::string>()> start;
    };
    
    完整演示

    //#define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <iostream>
    #include <map>
    
    namespace qi  = boost::spirit::qi;
    namespace phx = boost::phoenix;
    
    using Leaf    = int;
    using Node    = boost::make_recursive_variant< Leaf, std::map<std::string, boost::recursive_variant_> >::type;
    using SubTree = std::map<std::string, Node>;
    
    static Node sample = SubTree {
        { "simple", 100 },
        { "compound", SubTree { 
                  { "first", 200 },
                  { "second", 300 },
              }, },
        { "deep", SubTree {  
                { "nested", SubTree { 
                        { "compound", SubTree { 
                                  { "buried", 400 },
                                  { "secrets", 500 },
                              },
                        },
                    },
                },
            },
        }
    };
    
    int lookup(Node const& context, std::deque<std::string> path) {
        if (path.empty())
            return boost::get<Leaf>(context);
    
        auto& sub = boost::get<SubTree>(context);
    
        auto element = path.front();
        path.pop_front();
    
        try {
            return lookup(sub.at(element), std::move(path));
        } catch(std::out_of_range const& e) {
            throw std::runtime_error("'" + element + "' not found");
        }
    }
    
    namespace parser {
    
        template <typename Iterator>
        struct property : qi::grammar<Iterator, int()> {
            property() : property::base_type(start) {
                using namespace qi;
    
                name          = +(graph - char_(".][")); // not matching spaces please
                qualifiedName = name % '.';
    
                start = skip(ascii::space) ['[' >> qualifiedName >> ']']
                                [_val = phx::bind(lookup, phx::cref(sample), _1) ]
                        ;
    
                BOOST_SPIRIT_DEBUG_NODES((start)(qualifiedName)(name))
            }
    
          private:
            qi::rule<Iterator, std::deque<std::string>(), qi::ascii::space_type> qualifiedName;
            qi::rule<Iterator, std::string()> name;
            qi::rule<Iterator, int()> start;
        };
    }
    
    int main() {
        using It =  std::string::const_iterator;
        parser::property<It> calc;
    
        for (std::string const str : {
                    "[simple]",
                    "[compound.first]",
                    "[compound.second]",
                    "[deep.nested.compound.buried]",
                    "[deep.nested.compound.secrets]",
                    // whitespace is ok
                    "  [ compound.\tfirst ]",
                    // failing:
                    "[]",
                    "[missing]",
                    "[deep.missing.compound.buried]",
                    // whitespace not ok inside names
                    "  [ compound.\tfi rst ]",
                })
        try {
            std::cout << " ===== Input: '" << str << "'\n";
            It iter = str.begin(), end = str.end();
    
            int val;
            bool r = parse(iter, end, calc, val);
    
            if (r) {
                std::cout << "Parsing succeeded: " << val << "\n";
            } else {
                std::cout << "Parsing failed\n";
            }
    
            if (iter != end) {
                std::cout << " - Remaining unparsed input: '" << std::string(iter, end) << "'\n";
            }
        } catch(std::exception const& e) {
            std::cout << "Exception: " << e.what() << "\n";
        }
    }
    

    在回复一条丢失的注释(?)时,我将语法绑定到示例,因为这是您正在搜索的行(“如果您坚持,当然可以使用语义操作组合它”)。显然,我的建议是
    “事实上,我建议分离关注点:1.首先解析到std:vector 2.解析成功后,对其进行评估
    \u谢谢,我通过研究您的代码得到了所需的答案。对于缺少的注释,我在一分钟后意识到我自己的注释的答案。
    int lookup(Node const& context, std::deque<std::string> path);
    
    using Leaf    = int;
    using Node    = boost::make_recursive_variant< Leaf, std::map<std::string, boost::recursive_variant_> >::type;
    using SubTree = std::map<std::string, Node>;
    
    static Node sample = SubTree {
        { "simple", 100 },
        { "compound", SubTree { 
              { "first", 200 },
              { "second", 300 },
          }, },
        { "deep", SubTree {  
            { "nested", SubTree { 
                { "compound", SubTree { 
                      { "buried", 400 },
                      { "secrets", 500 },
        }, }, }, }, }, }
    };
    
    int lookup(Node const& context, std::deque<std::string> path) {
        if (path.empty())
            return boost::get<Leaf>(context);
    
        auto& sub = boost::get<SubTree>(context);
    
        auto element = path.front();
        path.pop_front();
    
        try {
            return lookup(sub.at(element), std::move(path));
        } catch(std::out_of_range const& e) {
            throw std::runtime_error("'" + element + "' not found");
        }
    }
    
    //#define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <iostream>
    #include <map>
    
    namespace qi  = boost::spirit::qi;
    namespace phx = boost::phoenix;
    
    using Leaf    = int;
    using Node    = boost::make_recursive_variant< Leaf, std::map<std::string, boost::recursive_variant_> >::type;
    using SubTree = std::map<std::string, Node>;
    
    static Node sample = SubTree {
        { "simple", 100 },
        { "compound", SubTree { 
                  { "first", 200 },
                  { "second", 300 },
              }, },
        { "deep", SubTree {  
                { "nested", SubTree { 
                        { "compound", SubTree { 
                                  { "buried", 400 },
                                  { "secrets", 500 },
                              },
                        },
                    },
                },
            },
        }
    };
    
    int lookup(Node const& context, std::deque<std::string> path) {
        if (path.empty())
            return boost::get<Leaf>(context);
    
        auto& sub = boost::get<SubTree>(context);
    
        auto element = path.front();
        path.pop_front();
    
        try {
            return lookup(sub.at(element), std::move(path));
        } catch(std::out_of_range const& e) {
            throw std::runtime_error("'" + element + "' not found");
        }
    }
    
    namespace parser {
    
        template <typename Iterator>
        struct property : qi::grammar<Iterator, int()> {
            property() : property::base_type(start) {
                using namespace qi;
    
                name          = +(graph - char_(".][")); // not matching spaces please
                qualifiedName = name % '.';
    
                start = skip(ascii::space) ['[' >> qualifiedName >> ']']
                                [_val = phx::bind(lookup, phx::cref(sample), _1) ]
                        ;
    
                BOOST_SPIRIT_DEBUG_NODES((start)(qualifiedName)(name))
            }
    
          private:
            qi::rule<Iterator, std::deque<std::string>(), qi::ascii::space_type> qualifiedName;
            qi::rule<Iterator, std::string()> name;
            qi::rule<Iterator, int()> start;
        };
    }
    
    int main() {
        using It =  std::string::const_iterator;
        parser::property<It> calc;
    
        for (std::string const str : {
                    "[simple]",
                    "[compound.first]",
                    "[compound.second]",
                    "[deep.nested.compound.buried]",
                    "[deep.nested.compound.secrets]",
                    // whitespace is ok
                    "  [ compound.\tfirst ]",
                    // failing:
                    "[]",
                    "[missing]",
                    "[deep.missing.compound.buried]",
                    // whitespace not ok inside names
                    "  [ compound.\tfi rst ]",
                })
        try {
            std::cout << " ===== Input: '" << str << "'\n";
            It iter = str.begin(), end = str.end();
    
            int val;
            bool r = parse(iter, end, calc, val);
    
            if (r) {
                std::cout << "Parsing succeeded: " << val << "\n";
            } else {
                std::cout << "Parsing failed\n";
            }
    
            if (iter != end) {
                std::cout << " - Remaining unparsed input: '" << std::string(iter, end) << "'\n";
            }
        } catch(std::exception const& e) {
            std::cout << "Exception: " << e.what() << "\n";
        }
    }
    
     ===== Input: '[simple]'
    Parsing succeeded: 100
     ===== Input: '[compound.first]'
    Parsing succeeded: 200
     ===== Input: '[compound.second]'
    Parsing succeeded: 300
     ===== Input: '[deep.nested.compound.buried]'
    Parsing succeeded: 400
     ===== Input: '[deep.nested.compound.secrets]'
    Parsing succeeded: 500
     ===== Input: '  [ compound.    first ]'
    Parsing succeeded: 200
     ===== Input: '[]'
    Parsing failed
     - Remaining unparsed input: '[]'
     ===== Input: '[missing]'
    Exception: 'missing' not found
     ===== Input: '[deep.missing.compound.buried]'
    Exception: 'missing' not found
     ===== Input: '  [ compound.    fi rst ]'
    Parsing failed
     - Remaining unparsed input: '  [ compound. fi rst ]'