我如何捕获原始输入到从精神语法合成输出? [英] How do I capture the original input into the synthesized output from a spirit grammar?

查看:150
本文介绍了我如何捕获原始输入到从精神语法合成输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个boost ::精神::气::语法和想原始文本的一部分复制到语法的合成输出结构(更具体地,该部分匹配的组件之一规则)。语法将最终被用作子语法提供了更为复杂的语法,所以我真的没有访问原始输入。

我猜,这可以通过语义动作或语法方面做,但我找不到,这是否不访问原始解析()的例子。

下面是我到目前为止有:

 的#include<&iostream的GT;
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>
#包括LT&;升压/融合/有/ adapt_struct.hpp>命名空间补气=的boost ::精神::补气;一个结构
{
    标准::字符串头;
    的std ::矢量<&INT GT;整型;
    标准::字符串inttext;
};BOOST_FUSION_ADAPT_STRUCT(
    一个,
    (标准::字符串,标题)
    (性病::矢量< INT>中整数)
    //(标准::字符串,inttext)
)模板< typename的迭代器>
结构解析器:补气::语法<迭代器,A()>
{
    解析器()语法分析器:: base_type(开始)
    {
        包头%=补气::语义[+补气::α-;
        整数%=补气::语义[齐:: int_%补气::字符_(_); //< ----捕捉到匹配这个inttext原文
        启动(%)=头>> ''>>整型;
    }    齐::规则<迭代器,标准::字符串()>头;
    齐::规则<迭代器,的std ::矢量<&INT GT;()>整型;
    齐::规则<迭代器,A()>开始;
};诠释的main()
{
    A输出;
    性病::字符串输入(出1,2_3);
    汽车ITER = input.begin();
    解析器< decltype(ITER)GT;磷;
    BOOL R =气::解析(ITER,input.end(),P,输出);
    如果(! - [R || ITER!= input.end())
    {
        性病::法院LT&;< 不解析;
    }
    其他
    {
        //想output.inttext是1,2_3
        性病::法院LT&;< output.header<< :&所述;&下; output.inttext<< - > [;
        为(自动和放大器;我:output.ints)
            性病::法院LT&;< I<< '';
        性病::法院LT&;< ']'<<的std :: ENDL;
    }
}


解决方案

类似于你问什么,而无需使用语义动作的内容:

 的#include<&iostream的GT;
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>
#包括LT&;升压/融合/有/ adapt_struct.hpp>
#包括LT&;升压/精神/库/有/ qi_iter_pos.hpp>命名空间补气=的boost ::精神::补气;
使用boost ::精神::库::补气:: iter_pos;结构ints_type
{
   的std ::矢量<&INT GT;数据;
   标准::字符串::为const_iterator开始;
   标准::字符串::为const_iterator结束;
};一个结构
{
    标准::字符串头;
    ints_type整数;
};BOOST_FUSION_ADAPT_STRUCT(
    ints_type,
    (标准::字符串::为const_iterator,开始)
    (性病::矢量< INT>中的数据)
    (标准::字符串::为const_iterator,结束)
)BOOST_FUSION_ADAPT_STRUCT(
     一个,
     (标准::字符串,标题)
     (ints_type,整数)
)模板< typename的迭代器>
结构解析器:补气::语法<迭代器,A()>
{
    解析器()语法分析器:: base_type(开始)
    {
        包头%=补气::语义[+补气::α-;
        整数%=补气::语义[iter_pos>>齐:: int_%补气::字符_(_)>> iter_pos]; //< ----捕捉到匹配这个inttext原文
        启动(%)=头>> ''>>整型;
    }    齐::规则<迭代器,标准::字符串()>头;
    齐::规则<迭代器,ints_type()>整型;
    齐::规则<迭代器,A()>开始;
};诠释的main()
{
    A输出;
    性病::字符串输入(出1,2_3);
    汽车ITER = input.begin();
    解析器< decltype(ITER)GT;磷;
    BOOL R =气::解析(ITER,input.end(),P,输出);
    如果(! - [R || ITER!= input.end())
    {
        性病::法院LT&;< 不解析;
    }
    其他
    {
        //想output.inttext是1,2_3
        性病::法院LT&;< output.header<< :&所述;&下;标准::字符串(output.ints.begin,output.ints.end)LT;< - > [;
        为(自动和放大器;我:output.ints.data)
            性病::法院LT&;< I<< '';
        性病::法院LT&;< ']'<<的std :: ENDL;
    }
}

使用语义动作:

 的#include<&iostream的GT;
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>
#包括LT&;升压/融合/有/ adapt_struct.hpp>
#包括LT&;升压/精神/库/有/ qi_iter_pos.hpp>命名空间补气=的boost ::精神::补气;
命名空间PHX =提振::凤;
使用boost ::精神::库::补气:: iter_pos;结构ints_type
{
   的std ::矢量<&INT GT;数据;
   标准::字符串inttext;
};一个结构
{
    标准::字符串头;
    ints_type整数;};BOOST_FUSION_ADAPT_STRUCT(
    ints_type,
    (性病::矢量< INT>中的数据)
    (标准::字符串,inttext)
)BOOST_FUSION_ADAPT_STRUCT(
     一个,
     (标准::字符串,标题)
     (ints_type,整数)
)模板< typename的迭代器>
结构解析器:补气::语法<迭代器,A()>
{
    解析器()语法分析器:: base_type(开始)
    {
        包头%=补气::语义[+补气::α-;
        整数=补气::语义[
                  (iter_pos>>气虚:: int_%补气::字符_(_)>> iter_pos)
                     [PHX :: at_c℃的>(气:: _ VAL)=气:: _ 2,
                      PHX :: at_c< 1 GT;(气:: _ VAL)= PHX ::构建<标准::字符串>(气:: _ 1,补气:: _ 3)]
               ];
        启动(%)=头>> ''>>整型;
    }    齐::规则<迭代器,标准::字符串()>头;
    齐::规则<迭代器,ints_type()>整型;
    齐::规则<迭代器,A()>开始;
};诠释的main()
{
    A输出;
    性病::字符串输入(出1,2_3);
    汽车ITER = input.begin();
    解析器< decltype(ITER)GT;磷;
    BOOL R =气::解析(ITER,input.end(),P,输出);
    如果(! - [R || ITER!= input.end())
    {
        性病::法院LT&;< 不解析;
    }
    其他
    {
        //想output.inttext是1,2_3
        性病::法院LT&;< output.header<< :&所述;&下; output.ints.inttext<< - > [;
        为(自动和放大器;我:output.ints.data)
            性病::法院LT&;< I<< '';
        性病::法院LT&;< ']'<<的std :: ENDL;
    }
}

I'm working on a boost::spirit::qi::grammar and would like to copy a portion of the original text into the synthesized output structure of the grammar (more specifically, the portion that matched one of the components of the rule). The grammar would ultimately be used as a sub-grammar for a more complicated grammar, so I don't really have access to the original input.

I'm guessing that this can be done through semantic actions or the grammar context, but I can't find an example that does this without access to the original parse().

Here's what I have so far:

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

namespace qi = boost::spirit::qi;

struct A
{
    std::string header;
    std::vector<int> ints;
    std::string inttext;
};

BOOST_FUSION_ADAPT_STRUCT(
    A,
    (std::string, header)
    (std::vector<int>, ints)
    //(std::string, inttext)
)

template <typename Iterator>
struct parser : qi::grammar< Iterator, A() >
{
    parser() : parser::base_type(start)
    {
        header %= qi::lexeme[ +qi::alpha ];
        ints %= qi::lexeme[ qi::int_ % qi::char_(",_") ]; // <---- capture the original text that matches this into inttext
        start %= header >> ' ' >> ints;
    }

    qi::rule<Iterator, std::string()> header;
    qi::rule<Iterator, std::vector<int>() > ints;
    qi::rule<Iterator, A()> start;
};

int main()
{
    A output;
    std::string input("out 1,2_3");
    auto iter = input.begin();
    parser<decltype(iter)> p;
    bool r = qi::parse(iter, input.end(), p, output);
    if( !r || iter != input.end() )
    {
        std::cout << "did not parse";
    }
    else
    {
        // would like output.inttext to be "1,2_3"
        std::cout << output.header << ": " << output.inttext << " -> [ ";
        for( auto & i: output.ints )
            std::cout << i << ' ';
        std::cout << ']' << std::endl;
    }
}

解决方案

Something similar to what you asked without using semantic actions:

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>

namespace qi = boost::spirit::qi;
using boost::spirit::repository::qi::iter_pos;

struct ints_type
{
   std::vector<int> data;
   std::string::const_iterator begin;
   std::string::const_iterator end;   
};

struct A
{
    std::string header;
    ints_type ints;
};

BOOST_FUSION_ADAPT_STRUCT(
    ints_type,
    (std::string::const_iterator, begin)
    (std::vector<int>, data)
    (std::string::const_iterator, end)
)

BOOST_FUSION_ADAPT_STRUCT(
     A,
     (std::string, header)
     (ints_type, ints)
)

template <typename Iterator>
struct parser : qi::grammar< Iterator, A() >
{
    parser() : parser::base_type(start)
    {
        header %= qi::lexeme[ +qi::alpha ];
        ints %= qi::lexeme[ iter_pos >> qi::int_ % qi::char_(",_") >> iter_pos ]; // <---- capture the original text that matches this into inttext
        start %= header >> ' ' >> ints;
    }

    qi::rule<Iterator, std::string()> header;
    qi::rule<Iterator, ints_type() > ints;
    qi::rule<Iterator, A()> start;
};

int main()
{
    A output;
    std::string input("out 1,2_3");
    auto iter = input.begin();
    parser<decltype(iter)> p;
    bool r = qi::parse(iter, input.end(), p, output);
    if( !r || iter != input.end() )
    {
        std::cout << "did not parse";
    }
    else
    {
        // would like output.inttext to be "1,2_3"
        std::cout << output.header << ": " << std::string(output.ints.begin,output.ints.end) << " -> [ ";
        for( auto & i: output.ints.data )
            std::cout << i << ' ';
        std::cout << ']' << std::endl;
    }
}

Using semantic actions:

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
using boost::spirit::repository::qi::iter_pos;

struct ints_type
{
   std::vector<int> data;
   std::string inttext; 
};

struct A
{
    std::string header;
    ints_type ints;

};

BOOST_FUSION_ADAPT_STRUCT(
    ints_type,
    (std::vector<int>, data)
    (std::string, inttext)
)

BOOST_FUSION_ADAPT_STRUCT(
     A,
     (std::string, header)
     (ints_type, ints)
)

template <typename Iterator>
struct parser : qi::grammar< Iterator, A() >
{
    parser() : parser::base_type(start)
    {
        header %= qi::lexeme[ +qi::alpha ];
        ints = qi::lexeme[
                  (iter_pos >> qi::int_ % qi::char_(",_") >> iter_pos)
                     [phx::at_c<0>(qi::_val)=qi::_2,
                      phx::at_c<1>(qi::_val)=phx::construct<std::string>(qi::_1,qi::_3)] 
               ]; 
        start %= header >> ' ' >> ints;
    }

    qi::rule<Iterator, std::string()> header;
    qi::rule<Iterator, ints_type() > ints;
    qi::rule<Iterator, A()> start;
};

int main()
{
    A output;
    std::string input("out 1,2_3");
    auto iter = input.begin();
    parser<decltype(iter)> p;
    bool r = qi::parse(iter, input.end(), p, output);
    if( !r || iter != input.end() )
    {
        std::cout << "did not parse";
    }
    else
    {
        // would like output.inttext to be "1,2_3"
        std::cout << output.header << ": " << output.ints.inttext << " -> [ ";
        for( auto & i: output.ints.data )
            std::cout << i << ' ';
        std::cout << ']' << std::endl;
    }
}

这篇关于我如何捕获原始输入到从精神语法合成输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆