草庐IT

c++ - 在语义 Action 中 boost spirit 改变变量值

coder 2024-02-16 原文

我想在语义操作中更改局部变量值,如下所示:

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;
using boost::phoenix::bind;

void dummy(const std::vector<char>& v, int& var)
{
    var = 7;
}

template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, std::string(), ascii::space_type>
{
public:
    x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
    {
        using namespace qi;
        int local_var = 0;
        start_rule = (+(char_ - ";"))[bind(dummy, _1, ref(local_var))];
        //repeat(ref(local_var))[some_rule];
    }
private:
    qi::rule<Iterator, std::string(), ascii::space_type> start_rule;
};

int main()
{
    typedef std::string::const_iterator iter;
    std::string storage("string;aaa");
    iter it_begin(storage.begin());
    iter it_end(storage.end());
    std::string read_data;
    using boost::spirit::ascii::space;
    x_grammar<iter> g;
    try {
        bool r = qi::phrase_parse(it_begin, it_end, g, space, read_data);
        std::cout << "Pass!\n";
    } catch (const qi::expectation_failure<iter>& x) {
        std::cout << "Error!\n";
    }
}

我在使用带有 boost 1.55 的 GCC 4.6.1 时遇到一些恼人的编译错误。

最佳答案

我不禁要注意,如果编译器错误让您烦恼,那么也许您应该编写有效的代码:/


指导性的帽子......

虽然这当然是一个轻率的评论,但它也具有一定的启发性。

我已经两次告诉你,在你的语法中使用构造函数局部变量的整个想法从根本上被打破了:

你想要的是

  • 继承属性
  • qi::本地人
  • maayyyyybe, maaaayyybe语法成员变量;需要注意的是,它们会使您的规则不可重入。

真正进入你头脑的重要事情是

Boost Spirit generates parser from expression templates. Expression templates are 90% static information (type only), and get "compiled" (.compile()) into "invokable" (.parse()) form.

Most importantly, while you can write control flow in your semantic actions, none of this actually executed at the definition site. It's "compiled" into a lazy actor that can later be invoked.

The generated parse will conditionally invoke the lazy actor when the corresponding parse expression matches


建设性的帽子...

看起来您只想使用函数转换属性。

以下是您可以执行的操作:

  1. 将转换作为语义操作的一部分,将结果放入常规属性(为解析器组合维护“功能”语义):

    qi::rule<Iterator, exposed(), Skipper> myrule;
    myrule = int_ [ _val = phx::bind(custom_xform, _1) ];
    

    custom_xform 是任何老派的可调用对象(包括多态可调用对象):

    exposed custom_xform(int i) { return make_new_exposed(i); } 
    // or
    struct custom_xfrom_t {
    
      template <typename> struct result { typedef exposed type; };
    
      template <typename Int>
        exposed operator()(Int i) const {
            return make_new_exposed(i);
        }
    };
    static const custom_xform_t custom_xform;
    
  2. 你可以添加一些语法糖[1]

    qi::rule<Iterator, exposed(), Skipper> myrule;
    myrule = int_ [ _val = custom_xform(_1) ];
    

    这需要将 custom_xform 定义为惰性 actor:

    phx::function<custom_xform_t> custom_xform; // `custom_xform_t` again the (polymorphic) functor
    

    You may note this wouldn't work for a regular function. You could wrap it in a calleable object, or use the BOOST_PHOENIX_ADAPT_FUNCTION macro to do just that for you

  3. 如果您想要更频繁地应用一些更复杂的转换,请考虑使用 Spirit Customization Points:

    如果您为属性选择特定类型(例如 Ast::MultiplicityAst::VelocityRanking,而不是 intdouble


[1] 使用 BOOST_SPIRIT_USE_PHOENIX_V3

关于c++ - 在语义 Action 中 boost spirit 改变变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23788538/

有关c++ - 在语义 Action 中 boost spirit 改变变量值的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  3. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  4. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  5. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  6. ruby-on-rails - 如何在 Rails Controller Action 上触发 Facebook 像素 - 2

    我有一个ruby​​onrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素

  7. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  8. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby-on-rails - 应用程序的名称是否可以作为变量使用? - 2

    当我创建一个Rails应用程序时,控制台:railsnewfoo我的代码可以使用字符串“foo”吗?puts"Yourapp'snameis"+app_name_bar 最佳答案 Rails.application.class将为您提供应用程序的全名(例如YourAppName::Application)。从那里您可以使用Rails.application.class.parent获取模块名称。 关于ruby-on-rails-应用程序的名称是否可以作为变量使用?,我们在StackOve

随机推荐