提升精神递归解析

时间:2015-04-02 14:45:47

标签: c++ recursion boost

我已经阅读了有关递归解析的其他主题,但这些解决方案对我来说还不够。

让我们有一个这么简单的解析器:

struct B;
typedef boost::variant<int, boost::recursive_wrapper<B> > A;
struct B {
    B() {
        static int l = 0;
        cout << "B() " << ++l << endl;
    }
    A a1;
    A a2;
};
// fusion adapt structs ....

typedef std::string::iterator iter;
typedef rule<iter, B()> BRule;
typedef rule<iter, A()> ARule;

ARule a;
BRule b;
a %= b | int_;
b %= a >> lit(',') >> a;
std::string s("5,8,3,1");

iter be = s.begin();
iter en = s.end();

B u;
parse(be, en, b, u);

我想解析类似's'的字符串:“5,1,3,9” - 这应该由B元素组成,其中包含2个仅包含整数的B元素。

它导致 - 根据站点名称 - 堆栈溢出。 当我添加parenthises:

b %= '(' >> a >> lit(',') >> a >> ')';
std::string s("((5,8),(3,1))");

......一切正常。

是否有可能避免使用parenthises并以这种方式使用解析器:

a %= b ....
b %= a ... 

?? 不一定是这样的符号,而是解析'3,4,5,6'而不是'((3,4),(5,6))'

2 个答案:

答案 0 :(得分:1)

不,你做不到。 PEG解析器只会在这两个规则之间来回反弹。

为什么不是你的解析器:

b %= int_ >> *(lit(',') >> int_);

或者,您经常会看到表单的结构:

expression %= primary >> *(lit(',') >> primary);
primary    %= '(' >> expression >> ')' | int_;

您也可以使用list parser并将其写为:

expression %= primary % lit(',');
primary    %= '(' >> expression >> ')' | int_;

答案 1 :(得分:0)

当然,对于逗号分隔的数字来说,更好的是

a %= b % ','
,但这只是一个显示问题本质的假例子。

如上所述,解决方案是:


    a %= b ....
    b %= any_rule_that_consumes_input >> .... a ....