关于 spirit

前面尝试了很长一段时间 spirit,总算开始对里面一些机制进行控制了。后面还有一些遗留问题有待解决和实验。

  • spirit::karma 是所谓的 generator,从某个角度来说就是 spirit::qi 的逆操作(从 C++ 的数据结构到外部的),因此感觉上就是类似写了个 operator<< 与 std::ostream 的关系;
  • spirit.qi 获得的结果似乎现在是没有优先级的,比如 1 + 2 * 3,按照一些语法规则获得的 tree 可能是先加后乘的。那么如何处理 AST 让它形成我们需要的 AST 呢?
  • 对于一些具体的文件格式,比如 JSON、XML、YAML 的简单情形是否能给出一些简单实用的 parser。

其实像 JSON 或者简单的 XML 都是可以比较容易搞定的,从前面的 XML 的例子,如果需要 attributes,我们可以简单的为每个 start_tag 增加一个字典用来存放每个 tag 的 attributes。

#include <boost/variant/recursive_variant.hpp>

struct mini_xml ;

typedef boost::variant<boost::recursive_wrapper<mini_xml>,
                       std::string> mini_xml_node ;
struct mini_xml {
  std::string name ;
  std::map<std::string, std::string> attr ;
  std::vector<mini_xml_node> children ;
} ;

对于 JSON 来说,如果不考虑整数等数值类型,对应的逻辑也很简单:

  • {} 里面的是 key/value 组成的字典,key 是 string 而 value 是 JSON 对象;
  • [] 里面是数组,每个元素是 JSON 对象;
  • 一个 JSON 对象或者是 string 或者是字典或者是数组;

一般来说确定了 EBNF 语法后设计合理的 data structure 即可,像 JSON 这个方式做的话可以如下定义

struct json ;
typedef std::vector<boost::recursive_wrapper<json> > json_array ;
typedef std::map<std::string, boost::recursive_wrapper<json> > json_dict ;
typedef boost::variant<std::string, json_array, json_dict> json ;

另外对于 YAML,似乎文档有几个步骤值得我们借鉴:

  • load 一个对象的过程包括 parse、compose 和 construct,像 spirit::qi 是不是仅仅解决了 parse 呢?感觉不像是
  • dump(对 spirit::karma 来说),这个逆过程包括 represent、serialize 和 present

从这个角度来说,spirit 很重要的一点是提供了这样一个 framework,需要不少人 contribute 对应具体 format 的 parser/generator 最后才能完成各种复杂的任务,这就是这个 repository 存在的意义。由于 spirit 是一个头文件 only 的 lib,我们可以从上面的例子学习到如何写一个更为复杂的问题。下面列举几个,

可惜还不能像 python 之类的通过某个 repository 直接 fetch 这些类似 package 的东西。哎…

——————-
And he that is eight days old shall be circumcised among you, every man child in your generations, he that is born in the house, or bought with money of any stranger, which is not of your seed.

Advertisements
关于 spirit

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s