【问题标题】:how do i find the location where a Spirit parser matched?如何找到 Spirit 解析器匹配的位置?
【发布时间】:2021-05-10 20:12:03
【问题描述】:

我正在解析一个由名称-值对组成的简单配置文件格式:

an_int_option 42;
a_string_option "foo";
an_identifier_option somevalue;

我有一个解析每个项目的基本规则:

  typedef boost::variant<int, double, std::string> config_value;
  struct config_item {
    std::string name;
    config_value value;
  };

  qi::rule<Iterator, config_value(), ascii::space_type> value;
  qi::rule<Iterator, config_item(), ascii::space_type> item;

  value = 
      identifier 
    | qstring
    | my_double 
    | qi::int_
    ;
  item = 
       identifier[at_c<0>(_val) = _1]
    >> value[at_c<1>(_val) = _1]
    >> ';'
    ;

这很好用,并为我提供了每个项目的 config_value。

现在我想将找到每个值的位置存储在输入文件中,这样如果用户配置了无效选项,我可以报告发生错误的文件行号和列号。

到目前为止,我发现的最佳选择是 raw[],它可以让我执行以下操作:

  item = 
       raw[ identifier ] [do_something_with_iterators(_1)]
    >> raw[ value ]      [do_something_with_iterators(_1)]
    >> ';'
    ;

...但是由于raw[] 丢弃了该属性,我的do_something_with_iterators 现在必须像在旧式Spirit 中那样手动解析值 - 当我已经有了解析值时,这似乎是很多不必要的工作。 .

【问题讨论】:

    标签: c++ boost boost-spirit


    【解决方案1】:

    您可以使用qi::raw[] 获取跨越匹配的源迭代器对。

    Qi Repository 中有一个方便的助手iter_pos,您可以使用它直接获取源迭代器,而无需使用qi::raw[]

    此外,通过一些语义动作技巧,您可以同时获得:

    raw[ identifier [ do_something_with_attribute(_1) ] ]
       [do_something_with_iterators(_1)]
    

    其实

    raw[ identifier [ _val = _1 ] ] [do_something_with_iterators(_1)]
    

    将接近“自然行为”。

    加倍努力

    要获取文件名/行/列值,您可以进行一些迭代算法或使用line_pos_iterator 适配器:

    #include <boost/spirit/include/support_line_pos_iterator.hpp>
    

    这有一些帮助行号/列跟踪的访问器函数。您可能可以在这里找到我的一些答案并附上示例。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 1970-01-01
    相关资源
    最近更新 更多