手写编译器-尾递归

本文介绍了手写编译器中如何处理尾递归,探讨了生产式解析和抽象语法树的概念,指出左递归问题并提供了消除方法。通过举例说明了递归在解析过程中的复杂性和潜在的深栈问题,对比了Spring Reactor与RxJava的处理方式,并强调了编译器利用尾递归避免深栈操作的重要性。文章最后分享了一段使用循环替代递归的代码实现。
摘要由CSDN通过智能技术生成

手写编译器

谈谈尾递归在变编译器中的实现

这一篇主要讲述生产式到java代码的生成过程;

何为生产式
expr ->   expr + term {print('+')}
        | expr - term {print('-')}
        | term
term ->  0   {print('0')}
        |1  {print('1')}
        |2  {print('2')}
         ...
        |9  {print('9')}

expr : 表示no ternimal (非终结符号,可以继续解析)
term : 表示no ternimal (非终结符号,可以继续解析)
0,1 … 9 : 数字(terminal 终结符号)
+ - : 操作符(terminal 终结符号)
| : 或者的意思,表示当前非终结符号可以解析的可能性
就expr 解析来说 有3种解析路劲,但是有的解析路径有可以又包含expr , 又可以继续解析,这是一个递归过程;
关于生产式的大致讲到这,总体概念是这样,想要更多细节还得深入。

生产式的解析

生产式的解析需要借助抽象语法树(Abstract and concrete tree)。比如9-5+2是符合上述生产式的,其抽象语法树

            +
        /       \
        -       2
    /       \
    9       5

我们知道上述的生生产式解析其实有左递归问题的(LR),可以就看成是 A代表expr。则 A->Aa|Aß|y 就是一个左递归产常见的例子,和上面的生产式类似;

消除该左递归之后可得到(消除方法见另一篇手写编译器-消除左递归

expr ->   term rest
rest -> + term {print('-')} rest
        | - term {print('-')} rest
        | £
term ->  0   {print('0')}
        |1  {print('1')}
        |2  {print('2')}
         ...
        |9  {print('9')}

该解析树用代码java伪代码实现

void expr(){
   
    term();reset();
}
void rest(){
   
    if(lookahead == '+'){
   
        match('+');term();print('+');rest();
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值