其他分享
首页 > 其他分享> > c – 请求解析器语法,使用boost spirit qi更好

c – 请求解析器语法,使用boost spirit qi更好

作者:互联网

我试图使用boost :: spirit :: qi来解析表达式.

表达很简单,也可以

> id,像x
>对象的成员,如obj.x.
>数组的元素,如arr [2]
>函数调用的结果. func(x,y)

对象的成员可以是数组或函数类型
x.y [2],x.y()是合法的.

函数结果可能是数组或对象
所以func(x,y).value,func(x)[4]也是合法的.

数组元素可以是对象或函数类型
所以arr [5] .y,arr [3](x,y)是合法的.

结合在一起,以下表达式应该是合法的:

x [1]().y(x,y,x.z,z [4] .y)().q [2] [3] .fun()[5] .x.y.z

所有这些[…](…)和.具有相同的优先权,从左到右.

我的语法是这样的

expression
    = postfix_expr
    | member_expr
    ;

postfix_expr = elem_expr | call_expr | id;
elem_expr = postfix_expr >> "[" >> qi::int_ >> "]";
call_expr = postfix_expr >> "(" >> expression_list >> ")";
member_expr = id >> *("." >> member_expr);

expression_list
    = -(expression % ",")

但它总是崩溃,我想也许某个地方有无限循环.

请给我一些关于如何解析这个语法的建议.

编辑
关注问题:
谢谢干部,它的确有效!

现在表达式可以正确解析,但我想引入一个新的ref_exp
这也是一个表达式,但不以()结束,因为函数结果不能放在赋值的左边.

我的定义是:

    ref_exp
        = id
        | (id >> *postfix_exp >> (memb_exp | elem_exp))
        ;

    postfix_exp
        = memb_exp
        | elem_exp
        | call_exp
        ;

    memb_exp = "." >> id;
    elem_exp = "[" >> qi::uint_ >> "]";
    call_exp = ("(" >> expression_list >> ")");

但是boost :: spirit :: qi无法解析这个,
我认为原因是(memb_exp | elem_exp)是postfix_exp的一部分,如何使它不解析所有,并留下最后一部分匹配(memb_exp | elem_exp)

ref_exp例子:x,x.y,x()[12] [21],f(x,y,z).x [2]
不是ref_exp:f(),x.y(),x [12]()

解决方法:

boost :: spirit :: qi is a descending parser;你的语法不能留下递归.

this question.

这里你肯定有一个左递归语法:postfix_expr – > elem_expr – > postfix_expr

编辑修复此问题的一种方法.

在我看来,你的表达式是一串带有可能后缀的id:[],(),..

expression = id >> *cont_expr;
cont_expr = elem_expr | call_expr | member_expr
elem_expr = "[" >> qi::int_ >> "]";
call_expr = "(" >> expression_list >> ")";
member_expr = "." >> expression;
expression_list = -(expression % ",")

编辑2如果您希望能够强制优先 – 例如括号:

expression = prefix_expr >> *cont_expr;
prefix_expr = id | par_expr
par_expr = "(" >> expression >> ")"

这样你甚至可以编写像x.(y [3] .foo)[5](fun(),foo(bar))这样的表达式 – 如果这有意义的话.

编辑3我在这里回答你的评论.

您需要左侧的赋值不是函数.这意味着你有一个特定的左手表达式后缀.让我们在评论中调用规则ref_exp.

ref_exp = id >> -( *cont_expr >> cont_ref );
cont_ref = elem_expr | member_expr;

标签:boost-spirit-qi,c,parsing,boost,boost-spirit
来源: https://codeday.me/bug/20190829/1761009.html