ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-08-29 14:08:06  阅读:232  来源: 互联网

标签:boost-spirit-qi c parsing boost boost-spirit


我试图使用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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有