【问题标题】:Boost spirit parsing objective-C like languageBoost 精神解析 Objective-C 类语言
【发布时间】:2016-02-09 22:31:32
【问题描述】:

我正在尝试用boost的精神重新实现iPhone越狱开发中的logo解析perl脚本。

输入的一个例子是:

%hook SBLockScreenView
-(void)setCustomSlideToUnlockText:(id)arg1
{
  arg1 = @"Changed the slider";
  %orig(arg1);
}
%end

到目前为止我有:

namespace logos
{
  namespace qi = boost::spirit::qi;
  namespace ascii = boost::spirit::ascii;

  struct class_hook
  {
    std::string class_name;
    std::string method_signature;
    std::string method_body;
  };

  template <typename Iterator>
  struct class_hook_parser : qi::grammar<Iterator, class_hook(), ascii::space_type>
  {
    class_hook_parser() : class_hook_parser::base_type(start)
    {
      using qi::int_;
      using qi::lit;
      using qi::on_error;
      using qi::fail;
      using qi::double_;
      using qi::lexeme;
      using ascii::char_;

      hooked_class %= lexeme[+(char_("a-zA-Z") - '-')];
      method_sig %= lexeme[+(char_) - '{'];
      method_body %= lexeme[+(char_ - '}')];

      start %=
        lit("%hook")
        >> hooked_class
        >> method_sig
        >> method_body
        >> lit("%end")
        ;

      on_error<fail>
    (
     start,
     boost::phoenix::ref(std::cout) << "Something errored!" << std::endl);

    }
    qi::rule<Iterator, std::string(), ascii::space_type> hooked_class;
    qi::rule<Iterator, std::string(), ascii::space_type> method_sig;
    qi::rule<Iterator, std::string(), ascii::space_type> method_body;
    qi::rule<Iterator, class_hook(), ascii::space_type> start;

  };

}

BOOST_FUSION_ADAPT_STRUCT(logos::class_hook,
              (std::string, class_name)
              (std::string, method_signature)
              (std::string, method_body))

typedef std::string::const_iterator iterator_type;
typedef logos::class_hook_parser<iterator_type> class_hook_parser;

using boost::spirit::ascii::space;
std::string::const_iterator
  iter = std::begin(tweak_source_code),
  end = std::end(tweak_source_code);

class_hook_parser g;
logos::class_hook emp;
bool r = phrase_parse(iter, end, g, space, emp);
if (r) {
  std::cout << "Got: " << boost::fusion::as_vector(emp) << std::endl;
}
else std::cout << "Something isn't working" << std::endl;

但奇怪的是,这只会打印出 Something isn't working 消息,而不是 on_fail 回调。我在解析中的错误在哪里?如何才能获得实际工作和信息丰富的解析错误消息?

【问题讨论】:

    标签: c++ boost boost-spirit


    【解决方案1】:

    你是说

    +(char_ - '{')
    

    而不是

    +(char_) - '{'
    

    您可能会要求正文以{ 开头,该{ 作为签名的一部分被拒绝。这是我的固定版本:

        hooked_class = +char_("a-zA-Z");
        method_sig   = +(char_ - '{');
        method_body  = '{' >> +(char_ - '}') >> '}';
    

    注意事项:

    • 删除船长也可以删除lexeme[] 指令。
    • 从“a-zA-Z”集中拒绝 - 是没有用的(它不在其中...)。
    • method_sig 现在包括所有空格(包括尾随换行符)
    • 使用 BOOST_SPIRIT_DEBUG 深入了解您的语法为何以神秘的方式起作用

    另请参阅:Boost spirit skipper issues

    Live On Coliru

    //#define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace logos
    {
        namespace qi    = boost::spirit::qi;
        namespace ascii = boost::spirit::ascii;
    
        struct class_hook
        {
            std::string class_name;
            std::string method_signature;
            std::string method_body;
        };
    
        template <typename Iterator>
            struct class_hook_parser : qi::grammar<Iterator, class_hook(), ascii::space_type>
        {
            class_hook_parser() : class_hook_parser::base_type(start)
            {
                using qi::int_;
                using qi::lit;
                using qi::on_error;
                using qi::fail;
                using qi::double_;
                using qi::lexeme;
                using ascii::char_;
    
                hooked_class = +char_("a-zA-Z");
                method_sig   = +(char_ - '{');
                method_body  = '{' >> +(char_ - '}') >> '}';
    
                start        = "%hook"
                           >> hooked_class
                           >> method_sig
                           >> method_body
                           >> "%end"
                           ;
    
                on_error<fail> (start,
                        boost::phoenix::ref(std::cout) << "Something errored\n"
                    );
    
                BOOST_SPIRIT_DEBUG_NODES((hooked_class)(method_sig)(method_body)(start))
            }
          private:
            qi::rule<Iterator, std::string()> hooked_class, method_sig, method_body;
            qi::rule<Iterator, class_hook(), ascii::space_type> start;
        };
    }
    
    BOOST_FUSION_ADAPT_STRUCT(logos::class_hook, class_name, method_signature, method_body)
    
    int main() {
        typedef std::string::const_iterator iterator_type;
        typedef logos::class_hook_parser<iterator_type> class_hook_parser;
    
        std::string const tweak_source_code = R"(
    %hook SBLockScreenView
    -(void)setCustomSlideToUnlockText:(id)arg1
    {
      arg1 = @"Changed the slider";
      %orig(arg1);
    }
    %end
            )";
    
        using boost::spirit::ascii::space;
        iterator_type iter = std::begin(tweak_source_code), end = std::end(tweak_source_code);
    
        class_hook_parser g;
        logos::class_hook emp;
    
        bool r = phrase_parse(iter, end, g, space, emp);
    
        if (r) {
            std::cout << "Got: " << boost::fusion::as_vector(emp) << "\n";
        } else {
            std::cout << "Something isn't working\n";
        }
    }
    

    打印

    Got: (SBLockScreenView -(void)setCustomSlideToUnlockText:(id)arg1
    
      arg1 = @"Changed the slider";
      %orig(arg1);
    )
    

    【讨论】:

    猜你喜欢
    • 2019-06-04
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多