C++ 是否有可能将灵气语法重新用作灵业语法?

C++ 是否有可能将灵气语法重新用作灵业语法?,c++,parsing,boost-spirit,boost-spirit-qi,boost-spirit-karma,C++,Parsing,Boost Spirit,Boost Spirit Qi,Boost Spirit Karma,我有一个Qi语法定义,用于解析输入。后来我有了一个业力产生器,以一种类似于输入的方式输出 这可能吗?似乎解析器语法可以自动转换为生成器语法(??) #包括 #包括 #包括 #包括 int main(){ //测试输入 std::string s=“Xx 1.233伪”; //输入变量 std::字符串元素; 双质量; std::伪字符串; 自动语法= boost::spirit::qi::lexeme[+(boost::spirit::qi::char_-'''-''-'\n')] >>提振::

我有一个Qi语法定义,用于解析输入。后来我有了一个业力产生器,以一种类似于输入的方式输出

这可能吗?似乎解析器语法可以自动转换为生成器语法(??)

#包括
#包括
#包括
#包括
int main(){
//测试输入
std::string s=“Xx 1.233伪”;
//输入变量
std::字符串元素;
双质量;
std::伪字符串;
自动语法=
boost::spirit::qi::lexeme[+(boost::spirit::qi::char_-'''-''-'\n')]
>>提振::精神::气::加倍_
>>boost::spirit::qi::lexeme[+(boost::spirit::qi::char_-'''-''-'\n');
bool r=boost::spirit::qi::短语(
s、 begin(),s.end(),
语法,
提升::精神::气::空间,元素,质量,伪
);

不幸的是,你不可能以一般的方式(或者至少我不知道如何)达到你想要的,但是如果你愿意只使用精神的有限子集,下面的方法可能会奏效

首先要知道的是,当您使用以下内容时:

int_ >> double_
你只需要一个Boost.Proto表达式,它描述了几个终端以及它们之间的关系。这个表达式本身并不“知道”如何解析一个int和一个double。每当你使用
parse
/
phrase\u parse
或将其中一个Proto表达式分配给
规则
Spirit“编译”该表达式表示一个域(气或业力),并创建执行实际工作的解析器/生成器

您可以看到一个小示例,其中显示了原型和编译Qi表达式的确切类型:

Raw proto type:
boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::spirit::terminal<boost::spirit::tag::int_> const&, boost::spirit::terminal<boost::spirit::tag::double_> const&>, 2l>

"Pretty" proto type:
shift_right(
    terminal(boost::spirit::tag::int_)
  , terminal(boost::spirit::tag::double_)
)

Compiled Qi type:
boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::any_int_parser<int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::any_real_parser<double, boost::spirit::qi::real_policies<double> >, boost::fusion::nil_> > >
我将尝试解释这是如何工作的。
MatcherN
在下面的示例中可以是:

  • proto::terminal
    :仅匹配该特定终端
  • proto::terminal
    :匹配以前未特别匹配的任何终端
  • proto::subscript
    :匹配
    省略[expr]
    其中
    expr
    可以是任何内容
  • proto::shift_right
    :匹配
    expr1>>expr2
    ,其中
    expr1
    expr2
    必须递归地符合
    ToKarma
    语法
  • proto::nary_expr
    :匹配任何n元(一元、二进制或实际上的n元,如函数调用
    a(b、c、d、e)
    ),其中表达式的每个元素都符合ToKarma语法
本例中所有的
TransformN
都是表达式生成器,下面是一些解释:

  • \u make_terminal(boost::spirit::tag::lexeme())
    :构建一个
    proto::terminal
    (请注意,有必要在标记之后添加
    ()
    ,如果您忘记了它们,您将得到一个可怕的错误)
  • \u make\u subscript(\u make\u terminal(tag::no\u different()),\u make\u terminal(tag::eps())
    :构建一个
    proto::subscript
    ,或与
    no\u different[eps]
    等效的文件
  • \u make_shift_left(托卡玛(原型::_left)、托卡玛(原型::_right))
    原型::_left
    表示取原始表达式的左撇子。
    托卡玛(原型::_left)
    意味着递归地将ToKarma语法/转换应用于原始表达式的lhs。整个
    \u make\u shift\u left
    基本上构建了
    转换后的lhs
    什么时候<
    proto::subscript,//省略[expr]->无定界[eps]
    proto::_make_subscript(proto::_make_terminal(boost::spirit::tag::no_divide()),proto:_make_terminal(boost::spirit::tag::eps())
    >,
    proto::terminal,//如果表达式是任何其他终端,则保持原样
    //运算符的翻译
    proto::when,//将'>>'更改为'{};
    模板
    无效测试(常量std::字符串和输入、常量解析器和解析器)
    {
    
    不幸的是,你不可能以一般的方式(或者至少我不知道如何)达到你想要的,但是如果你愿意只使用精神的有限子集,下面的方法可能会奏效

    首先要知道的是,当您使用以下内容时:

    int_ >> double_
    
    你只需要一个Boost.Proto表达式,它描述了几个终端以及它们之间的关系。这个表达式本身并不“知道”如何解析一个int和一个double。每当你使用
    parse
    /
    phrase\u parse
    或将其中一个Proto表达式分配给
    规则
    Spirit“编译”该表达式表示一个域(气或业力),并创建执行实际工作的解析器/生成器

    您可以看到一个小示例,其中显示了原型和编译Qi表达式的确切类型:

    Raw proto type:
    boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::spirit::terminal<boost::spirit::tag::int_> const&, boost::spirit::terminal<boost::spirit::tag::double_> const&>, 2l>
    
    "Pretty" proto type:
    shift_right(
        terminal(boost::spirit::tag::int_)
      , terminal(boost::spirit::tag::double_)
    )
    
    Compiled Qi type:
    boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::any_int_parser<int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::any_real_parser<double, boost::spirit::qi::real_policies<double> >, boost::fusion::nil_> > >
    
    我将尝试解释这是如何工作的。
    MatcherN
    在下面的示例中可以是:

    • proto::terminal
      :仅匹配该特定终端
    • proto::terminal
      :匹配以前未特别匹配的任何终端
    • proto::subscript
      :匹配
      省略[expr]
      其中
      expr
      可以是任何内容
    • proto::shift_right
      :匹配
      expr1>>expr2
      ,其中
      expr1
      expr2
      必须递归地符合
      ToKarma
      语法
    • proto::nary_expr
      :匹配任何n元(一元、二进制或实际上的n元,如函数调用
      a(b、c、d、e)
      ),其中表达式的每个元素都符合ToKarma语法
    本例中所有的
    TransformN
    都是表达式生成器,下面是一些解释:

    • \u make_terminal(boost::spirit::tag::lexeme())
      :构建一个
      proto::terminal
      (请注意,有必要在标记之后添加
      ()
      ,如果您忘记了它们,您将得到一个可怕的错误)
    • \u make\u subscript(\u make\u terminal(tag::no\u divide()),\u make\u terminal(tag::eps())
      struct Grammar : proto::or_<
                           proto::when<Matcher1,Transform1>,
                           proto::when<Matcher2,Transform2>,
                           Matcher3,
                           Matcher4
      >{};
      
      #include <iostream>
      #include <string>
      #include <tuple>
      #include <boost/config/warning_disable.hpp>
      #include <boost/spirit/include/qi.hpp>
      #include <boost/spirit/include/karma.hpp>
      #include <boost/fusion/include/std_tuple.hpp>
      
      namespace proto= boost::proto;
      
      
      struct ToKarma: proto::or_<
          //translation of directives
          proto::when<proto::terminal<boost::spirit::tag::lexeme>, proto::_make_terminal(boost::spirit::tag::verbatim())>, //lexeme -> verbatim
          proto::when<
              proto::subscript<proto::terminal<boost::spirit::tag::omit>,proto::_>, //omit[expr] -> no_delimit[eps]
              proto::_make_subscript(proto::_make_terminal(boost::spirit::tag::no_delimit()),proto::_make_terminal(boost::spirit::tag::eps()))
          >,
      
          proto::terminal<proto::_>, //if the expression is any other terminal leave it as is
      
          //translation of operators
          proto::when<proto::shift_right<ToKarma,ToKarma>, proto::_make_shift_left(ToKarma(proto::_left),ToKarma(proto::_right)) >, //changes '>>' into '<<'
          proto::when<proto::greater<ToKarma,ToKarma>, proto::_make_shift_left(ToKarma(proto::_left),ToKarma(proto::_right)) >, //changes '>' into '<<'
          proto::when<proto::minus<ToKarma,ToKarma>, ToKarma(proto::_left)>, //changes 'expr-whatever' into 'expr'
      
          proto::nary_expr<proto::_,proto::vararg<ToKarma> > //if it's anything else leave it unchanged and recurse into the expression tree
      >{};
      
      
      template <typename ... Attr, typename Parser>
      void test(const std::string& input, const Parser& parser)
      {
          std::cout << "Original: \"" << input << "\"\n";
      
          std::tuple<Attr...> attr;
      
          std::string::const_iterator iter = input.begin(), end = input.end();
      
          bool result = boost::spirit::qi::phrase_parse(iter,end,parser,boost::spirit::qi::space,attr);
      
          if(result && iter==end)
          {
              ToKarma to_karma;
              std::cout << "Generated: \"" << boost::spirit::karma::format_delimited(to_karma(parser), boost::spirit::karma::space, attr) << '"' << std::endl;
          }
          else
          {
              std::cout << "Parsing failed. Unparsed: ->" << std::string(iter,end) << "<-" << std::endl;
          }
      }
      
      
      
      int main(){
          using namespace boost::spirit::qi;
      
          test<std::string,double,std::string >("Xx     1.233    pseudo", lexeme[+(char_-' '-'\n')] >> double_ >> lexeme[+(char_-' '-'\n')]);
          test<int,double>("foo 1 2.5", omit[lexeme[+alpha]] > int_ > double_);
      }