[编译原理]表达式语法分析——递归子程序法(Python & C++)

〔重庆理工大学〕编译原理语法分析源代码【实验一 设计递归下降子程序对语法分析】 本文描述了一个语法分析实验任务,要求基于给定的类C语言文法扩展新的语法成分并实现递归下降分析器。实验需要完成以下工作:1) 补充for语句、do-while语句、continue/break语句和函数调用的文法规则;2) 设计递归下降子程序分析所有语法成分;3) 输出包含词法信息和语法成分名称的结果文件。输入文件为input.txt,输出文件为output.txt需包含单词信息和语法成分标记(如<FunctionDef>)。文章提供了部分参考代码和基础文法规则,涉及程序结构、声明、控制语句和表达 阅读详情

表达式语法分析——递归子程序法

Problem Description

递归子程序法是一种确定的自顶向下语法分析方法,要求文法是LL(1)文法。它的实现思想是对应文法中每个非终结符编写一个递归过程,每个过程的功能是识别由该非终结符推出的串,当某非终结符的产生式有多个候选式时能够按LL(1)形式唯一地确定选择某个候选式进行推导。请根据下面的表达式LL(1)文法,构造递归子程序,完成对表达式的语法分析。

表达式文法如下:

E→TG

G→+TG | ε

T→FS

S→*FS | ε

F→(E) | i

对于给定的输入串(长度不超过50个符号),请输出分析过程中用到的所有产生式,并指明该输入串是否为该文法能生成的表达式,输出共11行,前10行每行两个数据用空格隔开,表示推导时所用产生式顺序号(从0开始),最后一行是accept,表示i+i*i是文法能生成的合法表达式。注:其中&符号代表文法中的ε符号。

Input

输入数据只有一行,代表待分析的符号串,以#号结束

Output

输出推导过程中所有的产生式,按照使用顺序给出。输出详细说明见题目描述中的例子。

Sample Input

i+i*i#

Sample Output

0 E–>TG
1 T–>FS
2 F–>i
3 S–>&
4 G–>+TG
5 T–>FS
6 F–>i
7 S–>*FS
8 F–>i
9 S–>&
10 G–>&
accept

Python版本

# E→TG
# G→+TG | ε
# T→FS
# S→*FS | ε
# F→(E) | i
class Un(object):

    def __init__(self, num, cur, st):
        self.num = num
        self.cur = cur
        self.st = st

    def E(self):

        print('{} E-->TG'.format(self.num))
        self.num += 1
        self.T()
        self.G()

    def T(self):

        print('{} T-->FS'.format(self.num))
        self.num += 1
        self.F()
        self.S()

    def G(self):

        if self.st[self.cur] == '+':
            print('{} G-->+TG'.format(self.num))
            self.num += 1
            self.cur += 1
            self.T()
            self.G()
        else:
            print('{} G-->&'.format(self.num))
            self.num += 1

    def F(self):
        if self.st[self.cur] == 'i':
            print('{} F-->i'.format(self.num))
            self.num += 1
            self.cur += 1
        elif self.st[self.cur] == '(':
            print('{} F-->(E)'.format(self.num))
            self.num += 1
            self.cur += 1
            self.E()
            if self.st[self.cur] == ')':
                self.cur += 1
            else:
                print("error")
                exit(0)
        else:
            print("error")
            exit(0)

    def S(self):
        # print(self.cur)
        if self.st[self.cur] == '*':
            print('{} S-->*FS'.format(self.num))
            self.num += 1
            self.cur += 1
            self.F()
            self.S()
        else:
            print('{} S-->&'.format(self.num))
            self.num += 1


if __name__ == '__main__':

    aa = input()
    aa = list(aa)
    aa.append('')  #给列表末尾添加一个空元素,防止溢出
    a = Un(0, 0, aa)
    a.E()
    if a.st[a.cur] != '#':
        print("error")
    else:
        print('accept')

C++版本

#include<bits/stdc++.h>
using namespace std;
string s;
int N=0;
int cur =0;
void E();
void T();
void G();
void F();
void S();

int main(){
    cin>>s;
    if(s[cur]!='i'&&s[cur]!='('){
        cout<<"error"<<endl;
        exit(0);
       }
    E();
    if(s[cur]=='#')
        cout<<"accept"<<endl;
    else
        cout<<"error"<<endl;

}
void E(){
    cout<<N<<" E-->TG"<<endl;
    N++;
    T();
    G();
}
void T(){
    cout<<N<<" T-->FS"<<endl;
    N++;
    F();
    S();
}
void G(){
    if(s[cur]=='+')
    {
         cout<<N<<" G-->+TG"<<endl;
         N++;
         cur++;
         T();
         G();
    }
    else
    {
        cout<<N<<" G-->&"<<endl;
        N++;
    }
}
void F(){
    if(s[cur]=='(')
    {
        cout<<N<<" F-->(E)"<<endl;
        N++;
        cur++;
        E();
        if(s[cur]==')'){
            cur++;
        }
        else
        {
            cout<<"error"<<endl;
            exit(0);
        }
    }
    else if(s[cur]=='i'){
        cout<<N<<" F-->i"<<endl;
        N++;
        cur++;
    }
//        else if(s[cur]=='i'){
//        cout<<N<<" F-->i"<<endl;
//        N++;
//        cur++;
//    }

}
void S(){
    if(s[cur]=='*'){
        cout<<N<<" S-->*FS"<<endl;
        N++;
        cur++;
        F();
        S();
    }
    else{
        cout<<N<<" S-->&"<<endl;
        N++;
    }
}

〔重庆理工大学〕编译原理实验报告【语法分析实验】 编译原理实验报告摘要(149字) 本实验实现了基于递归下降法的Sample语言语法分析器,重点完成:1)文法扩展与LL(1)改造,新增for/do-while/break/continue/函数调用等语法成分;2)设计分层递归子程序,建立非终结符到分析函数的映射,通过表达式分析链处理运算符优先级;3)构建统一AST节点体系,实现语法成分到抽象语法树的精确转换;4)开发错误处理机制,定义11类语法错误编码,实现错误定位与局部化恢复。实验输出符合规范的AST结构及错误信息,验证了递归下降分析法在编译器前端中的有 阅读详情

相关推荐

语法分析实验报告含代码:递归子程序法与LL(1)预测分析实现详解

从编译原理中的词法分析到语法分析,是构建编译器不可回避的核心环节。语法分析负责判定token序列是否属于某文法,并还原推导过程。递归子程序法与预测分析法(LL(1))是两种主流实现路线:前者用函数递归模拟产生式,后者依赖FIRST/FOLLOW集合构造分析表。理解这些原理不仅有助于完成课程实验,也为开发代码诊断工具、集成IDE语法报错提供基础。表达式文法、消除左递归、分析表构建、错误定位等技术贯穿编译原理实践,广泛应用于教学实验、静态分析、语言前端等场景。本文结合C与Python代码,系统讲解两种方法的实现

weixin_32175665的博客 187

编译原理实验(三):递归下降子程序

表达式文法的递归下降分析器设计

欢迎来到 晨 的博客 4149

编译原理词法分析加语法分析实验:手写DFA与递归下降实现

编译原理是计算机体系中的核心课程,而词法分析与语法分析则是编译器前端的两大基石。词法分析将源码字符流转化为有意义的token序列,其常见实现包括正则表达式匹配与手写有限状态自动机;语法分析则依据文法规则对token流进行结构化解析,递归下降法通过函数嵌套直接映射产生式,天然适配LL(1)文法。掌握这两项技术不仅有助于理解编译器的整体工作流程,也能提升对程序语言设计与工程实现的综合认知。在工程实践中,从词法状态转移表到语法分析树的构建,常广泛用于代码编辑器语法高亮、静态代码分析、IDE错误提示及自定义DSL解

weixin_34192816的博客 584

编译原理第五章——语法分析(上)

# 编译原理第五章——语法分析(上)

m0_62740859的博客 1178

编译原理实验指南:词法分析与语法分析的实现与报告写作

编译原理是计算机科学的核心课程,词法分析和语法分析则是编译器前端的两大基石。词法分析通过状态转换图将字符流转换为token流,是理解有限自动机的最佳实践;语法分析则依据上下文无关文法,通过递归下降或预测分析将token流组织成语法树。掌握这两项技术,不仅能深入理解编译器的运行机制,也能为构建解释器、DSL、代码格式化工具等工程实践提供基础能力。从正则表达式到LL(1)文法,从手写解析器到Flex/Bison自动生成工具,围绕词法分析和语法分析的关键知识点,结合实际实验中的调试技巧与报告验收标准,帮助读者构建

weixin_42116058的博客 64

编译原理实验二:语法分析程序设计与实现全流程

语法分析是编译原理的核心环节,负责将词法分析产生的 token 流转换为语法树。其原理基于上下文无关文法,通过递归下降或 LR 分析技术实现语法结构识别。掌握语法分析能深入理解编译器前端工作流程,提升程序语言处理能力。在编译器开发、代码分析工具、领域特定语言等场景中广泛应用。本文以实验二为例,详细讲解从文法设计、算法选择到代码实现的完整过程,涵盖递归下降和 LR 分析,并融入 token 流设计和错误恢复等热词,帮助读者快速上手语法分析程序开发。

weixin_34116482的博客 308

编译原理|递归下降分析子程序

递归下降分析子程序 一、实验目的 掌握最基本的自顶向下分析方法,即递归下降子程序方法,理解其特点和适用范围(回溯,左递归等现象),锻炼递归调用程序的构造方法。 二、实验内容 给定CP语言中简单算术表达式文法G[E]: E→TE’ E’→ATE’|ε T→FT’ T’→MFT’ |ε F→(E) | i A → + | - M → * | / 根据该文法,编写递归下降分析子程序。 【说明】 终结符号...

匿名用户小易 5656

编译原理课设:Python手写词法分析、递归下降语法分析与三地址码生成

编译原理是计算机科学的核心课程,其中词法分析与语法分析是构建编译器的两大基石。词法分析将源代码字符流拆分为有意义的Token序列,语法分析则依据文法规则将Token组织成抽象语法树。在工程实践中,手写递归下降解析器能更直观地控制解析流程,配合三地址码生成中间代码,即可构成一个可运行的小型编译器。这套技术链路不仅适用于教学实验,也是理解工业级编译器前端与中间代码生成的关键路径。对于正在完成编译原理课程设计的同学,从手写词法分析器开始,逐步搭建递归下降语法分析器,并生成三地址码,既能满足验收标准,又能真正掌握编

weixin_33326218的博客 110

编译原理个人作业--第四章

考虑文法$G_1$: $$S \rightarrow a|\land|(T) \\ T\rightarrow T,S|S$$ 先复习左递归如何消除 `原书p69页` 1. 类似于$P\rightarrow Pa|b$的形式,可以改写成 - $P\rightarrow bP^{'}$ - $P^{'}\rightarrow aP^{'}|\epsilon$

JamSlade的博客 2541

编译原理 递归子程序方法 代码

1.定义部分:定义常量、变量、数据结构。 2.初始化:从文件将输入符号串输入到字符缓冲区中。 3.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。

编译原理-递归子程序 c++源码

编译原理-递归子程序 c++源码 编译原理-递归子程序 c++源码 编译原理-递归子程序 c++源码

编译原理——递归程序基本思想和编程方法

一、实验目的: (1) 掌握递归程序基本思想和编程方法。 二、实验内容: 查阅资料了解递归思想和递归程序编写; 递归(recursion):程序调用自身的编程技巧。 递归满足2个条件: 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 调试、编译、自定义主程序,运行程序。 三、实验原理: 递归(recursion)就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。 递归通常用来解决结构自相似的问题。所谓结构自相似,是

TTTSEP9TH2244的博客 2166

编译原理中采用递归下降子程序方法实现语法分析的程序

程序代码简单,容易理解,采用递归下降子程序实现语法分析,希望给大家带来帮助

递归子程序法 vs LL(1) 分析表:2 种自顶向下语法分析实现对比

本文深入对比了递归子程序法与LL(1)分析表在自顶向下语法分析中的实现差异。通过SysY语言案例,详细解析了两种方法在文法处理、错误恢复和代码结构等方面的特点,帮助开发者根据项目需求选择合适的技术方案。递归子程序法适合需要高性能和灵活错误处理的场景,而LL(1)分析表则在维护成本和文法扩展性上更具优势。

weixin_34347651的博客 364

Shopee App加密算法逆向实战:从抓包到libshpssdk.so的深度解析

本文详细解析了Shopee App加密算法的逆向过程,从网络抓包发现加密参数入手,通过Frida动态Hook定位到Java层关键方法,并深入追踪至Native层的libshpssdk.so核心函数。文章结合实战演示了如何利用Unidbg模拟执行环境进行算法分析与验证,并探讨了核心参数生成逻辑及风控规避要点,为移动安全与逆向工程研究提供了完整的技术路径。

weixin_28347369的博客 527

Claude Code 完整使用教程(2026最新版)

《Claude Code 完整使用教程(2026最新版)》摘要: Claude Code 是 Anthropic 公司推出的智能编程工具,通过自然语言对话实现代码编写、调试和重构。本教程基于 v2.1.101 版本,涵盖安装配置、核心功能及最新特性。主要内容包括: 多平台安装方式(macOS/Linux/Windows) 桌面应用专属功能如并行会话、定时任务和语音模式 模型选择指南(Sonnet/Opus/Haiku) 快速入门示例:5分钟创建Node.js项目 核心功能:代码读写、命令执行、Git集成等

程序猿_三产 2万+

编译原理课程设计实验 4:语义分析和中间代码生成器-赋值表达式

本文实现了一个递归下降翻译器,用于处理赋值语句的语义分析和中间代码生成。系统包含词法分析、语法分析和语义分析模块,最终生成四元式中间代码。针对测试表达式"a=6/b+5*c-d",程序成功完成了词法分析、语法分析、语义分析、输出处理。

2401_84149564的博客 1302

【同花顺公式编辑教程】第4章 功能函数

本章节主要给出大部分能够运行且常用的同花顺指标编辑器提供的函数。其中,计算类函数不作演示,绘图类函数提供示例及示例运行结果。

LiaoYi2016218的博客 2万+

递归下降实现LL(1)文法分析C语言与Python实现

对文法G的句子进行确定的自顶向下语法分析的充分必要条件是,G的任意两个具有相同左部的产生式A—&amp;gt;α|β 满足下列条件: (1)如果α、β均不能推导出ε,则 FIRST(α) ∩ FIRST(β) = ∅。 (2)α 和 β 至多有一个能推导出 ε。 (3)如果 β *═&amp;gt; ε,则 FIRST(α) ∩ FOLLOW(A) = ∅。 将满足上述条件的文法称为LL(1)文法。 例子: E-...

徐奕的专栏 4933

如何判断一个程序员的技术比你强?

技术大佬与普通程序员之间存在明显的认知差异:前者善于将复杂问题抽象为经典计算机科学问题,用声明式代码替代过程式逻辑;对异常和边界条件极度敏感,具备系统化的排查方法论;代码追求高可读性而非炫技,且执着于底层原理研究。这种技术压制体现在解决问题的确定性上——通过扎实的理论功底和工程直觉,快速定位问题本质,而非依赖试错或搜索。真正的技术实力源于对底层逻辑的深刻理解和对系统稳定性的敬畏。

wldtzzming的专栏 1088

SAP ABAP ALV表格实战:5分钟搞定单元格下拉框配置(附完整代码)

本文详细介绍了在SAP ABAP开发中如何快速配置ALV表格的单元格下拉框功能,通过5分钟实战教程帮助开发者掌握关键步骤。文章包含完整的ABAP代码示例,涵盖下拉值定义、字段目录配置及ALV控件绑定等核心操作,特别适合需要实现财务系统费用类型选择或采购系统物料分类等场景的开发者参考。

weixin_28331555的博客 110

<编译原理> 左递归消除算法

本文介绍消除文法左递归的算法,并输出新文法产生式。 消除左递归在语法分析阶段是比较重要的一个过程,尤其在自顶向下的分析过程中,编译器会尝试各个推导式,如果存在左递归,那么推导过程将会用永无止境。 比较显式的左递归我们称之为直接左递归,比如说 其中表示非空的表达式,表示不以非终结符A开头的表达式。 那么我们知道对于非终结符A来说,最终只能以到来结束,否则依然会含有非终结符...

weixin_52435933的博客 895

华为、Cisco、H3C、中兴网络设备如何配置syslog日志采集

华为、Cisco、H3C、中兴网络设备如何配置syslog日志采集

weixin_40239644的博客 8706

【编译原理】让我们来构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 6.)(python/c/c++版)(笔记)

【编译原理】让我们来构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 4.) 文章目录python代码C语言代码总结 今天是这一天:) “为什么?” 你可能会问。原因是今天我们结束了对算术表达式的讨论(好吧,几乎)通过在我们的语法中添加括号表达式并实现一个解释器,该解释器将能够评估具有任意深度嵌套的括号表达式,例如表达式 7 + 3 * (10 / (12 / (3 + 1) - 1))。 让我们开始吧,好吗? 首先,让我们修改语法以支持括号内的表达式。正如

Dontla的博客 786

《深入掌握MongoDB数据库》 - 专栏介绍和目录

本专栏系统讲解MongoDB从基础到高级的全栈知识,涵盖安装配置、核心操作、性能优化、安全运维等核心内容。基础部分包括CRUD操作、数据类型、查询语法等入门知识;进阶部分深入索引优化、聚合查询、事务处理等高级特性;核心原理解析存储引擎与数据格式;安全运维则聚焦访问控制、认证机制、审计日志等企业级实践。通过实战案例与最佳实践,帮助开发者全面掌握MongoDB在不同场景下的应用,适合各层次技术人员系统学习。

数据知道的博客 2996

Mathematica 训练课(12)常用注释方法

Mathematica从入门到进阶

qq_25018077的博客 9075
上一篇: 笔记:2017编译原理-运行时空间组织管理&优化&目标代码生成
下一篇: Python实验四:文本处理和文件内容操作
ArtinCode
博客等级 码龄9年 23粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值