语法分析程序


文章目录

  • 语法分析程序
    • 一、作业目的和要求
    • 二、作业内容
    • 三、作业要求
    • 四、结果分析

一、作业目的和要求

通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,实现并进一步掌握常用的语法分析方法。


二、作业内容

选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象(例如表达式、if、while、for等等),给出其文法规则描述(注意,文法规则的描述要符合所选分析方法的要求,比如用LL(1)分析法,文法必须是LL(1)文法),设计并实现一个完整的语法分析程序。

  • 输入:源程序以文件的形式输入。
  • 输出:对于输入的源程序,如果输入源程序是给定文法定义的合法程序,则输出”success”,如果不是,即输入源程序有错误,则输出“Error”,并且尽可能指出出错位置和原因。

三、作业要求

1、说明语法分析的源语言是什么?
能分析的语法成分有哪些(比如if、while、表达式、switch等等)。
给出每个语法规则的文法描述。(可以自定义语法成分,设计合理的语法规则。)

运用的Java语言写成的语法分析程序,
语法成分包括:if选择结构,while循环结构,for循环结构。

2、说明选择的语法分析方法是哪种?描述总体设计思路和主要的流程图。

语法分析的方法是LL(1)文法。

  • 设计思路:

  • 1.构造单个文法符号X的first集:
    如果X为终结符,First(X)=X;
    如果X->ε是产生式,把ε加入First(X);
    如果X是非终结符,如X->YZW。从左往右扫描产生式右部,把First(Y)加入First(X); 如果First(Y)不包含ε,表示Y不可为空,便不再往后处理;如果First(Y)包含ε,表示Y可为空,则处理Z,依次类推。
    构造文法符号串的first集,如:X->YZW;求YZW的first集
    从左往右扫描该式,加入其非空first集:把First(Y)加入First(YZW)
    若包含空串,处理下一个符号:如果First(Y)包含空串,便处理Z;不包含就退出;处理到尾部,即所有符号的first集都包含空串 把空串加入First(YZW)。

  • 2.在计算First(X)集之后的基础上:
    (1)$属于FOLLOW(S),S是开始符;
    (2)查找输入的所有产生式,确定X后紧跟的终结符;
    (3)如果存在A->αBβ,(α、β是任意文法符号串,A、B为非终结符),把first(β)的非空符号加入follow(B);
    (4)如果存在A->αB或A->αBβ 但first(β)包含空,把follow(A)加入follow(B)。

  • 3.构造预测分析表:
    对于每个产生式A->α,first(α)中的终结符a,把A->α加入M[A,a]。
    如果空串在first(α)中,说明可为空,找它的follow集,对于follow(A)中的终结符b,把A->α加入M[A,b];
    如果空串在first(α)中,且 “$”也在follow(A)中,说明A后可以接终结符,故把A->α加入M[A,$]中。

  • 4.执行分析:
    输入一个串,文法G的预测分析表,输出推导过程:
    $ 和 开始符S入栈,栈顶符号X,index指向分析串的待分析符号a。
    栈非空执行以下循环:
    如果X==a,表示匹配,符号栈弹出一个,index++指向下一个符号;
    否则,如果X是终结符,出错;
    否则,如果查表为error,出错;
    否则,查表正确,弹出栈顶符号,把其右部各个符号进栈,令X为栈顶符号。

  • 流程图:

3、编程实现,程序中编写的各种函数,需要给出注释,说明函数的作用。
通过实现接口中的方法来完成语法分析的功能。

package Try;interface MyAnalyseFun {void Init();//初始化void getVnVt();//获取非终结符和终结符的集合void getFirst(Character c);//first集void getFirst(String s);//任意字符的first集void getFollow(char c);//follow集void createTable();//构造表void analyzeLL();//LL(1)分析过程String find(char X, char a);//查找void insert(char X, char a,String s);//插入void displayLL();//输出分析过程void ouput();//其他输出信息
}

    package Try;import java.io.*;import java.util.*;public class MyAnalyse implements MyAnalyseFun{/*** 几个比较重要的参数* @param MyfirstSet 终结符的first集合* @param MyfirstSetX 任意符号的first集合* @param start 文法的开始符* @param MyfollowSet follow集* @param VnSet 终结符的集合* @param VtSet 终结符的集合* @param inputStrings 文法拓展的输入* @param outputSet 输出的集合* @param table 分析表* @param MyAnaStatck 分析栈* @param strInput 需要使用预测分析器的输入串* @param MyAction 分析动作* @param Index 分析的索引值*///从文件中读入时后台无法识别空串ε,因此用符号&代替空串ε//first集是终结符的first集protected HashMap<Character, HashSet<Character>> MyfirstSet = new HashMap<>();//firstX集是指任意符号串的first集protected HashMap<String, HashSet<Character>> MyfirstSetX = new HashMap<>();//文法的开始符protected Character start = 'S';//follow集protected HashMap<Character, HashSet<Character>> MyfollowSet = new HashMap<>();//存储非终结符的结合protected HashSet<Character> VnSet = new HashSet<>();//存储终结符的结合protected HashSet<Character> VtSet = new HashSet<>();protected HashMap<Character, ArrayList<String>> outputSet = new HashMap<>();//输入文法//S->a|^|(T)//T->SU//U->,SU|&
//    protected String [] inputStrings = {   "S->a",
//                                        "S->^",
//                                        "S->(T)",
//                                        "T->SU",
//                                        "U->,SU",
//                                        //"U->ε",
//                                        "U->&"   };//定义分析表protected String [][] table;//分析栈protected Stack<Character> MyAnaStatck = new Stack<>();//定义要分析的输入串protected String strInput = "(a,a)$";//对动作的初始化protected String MyAction = "";int Index = 0;//从文件中读入protected String[] inputStrings = getSource();protected MyAnalyse() {}public static void main(String[] args){MyAnalyse test = new MyAnalyse();test.getVnVt();test.Init();test.createTable();test.analyzeLL();test.ouput();}//从文件中读入文法的方法public  static  String[] getSource(){StringBuffer temp = new StringBuffer();FileInputStream fis= null;try {fis = new FileInputStream("E:\\readin.txt");byte[] buff=new byte[1024];int len=0;while((len=fis.read(buff))!=-1){temp.append(new String(buff,0,len));}} catch (Exception e) {e.printStackTrace();} finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}return temp.toString().split("\n");}//初始化@Overridepublic void Init() {for (String s1 : inputStrings) {//"S->a",//"S->^",//"S->(T)",//"T->SU",//"U->,SU",//"U->&"String[] str = s1.split("->");//通过符号“->”分隔每行的文法char c = str[0].charAt(0);//取得左边的非终结符ArrayList<String> list = outputSet.containsKey(c) ? outputSet.get(c) : new ArrayList<>();list.add(str[1]);//添加文法右边的内容到集合中outputSet.put(c, list);}//求非终结符的first集for (Character c1 : VnSet)getFirst(c1);for (Character c2 : VnSet) {ArrayList<String> l = outputSet.get(c2);for (String s2 : l)getFirst(s2);}//求出follow集getFollow(start);for (Character c3 : VnSet) {getFollow(c3);}}@Overridepublic void getVnVt() {//取出终结符和非终结符的集合for (String s3 : inputStrings) {String[] str = s3.split("->");VnSet.add(str[0].charAt(0));}for (String s4 : inputStrings) {String[] str = s4.split("->");String right = str[1];for (int i = 0; i < right.length(); i++)if (!VnSet.contains(right.charAt(i)))VtSet.add(right.charAt(i));}}@Overridepublic void getFirst(Character c) {ArrayList<String> list = outputSet.get(c);HashSet<Character> set = MyfirstSet.containsKey(c) ? MyfirstSet.get(c) : new HashSet<Character>();// c为终结符 直接添加if (VtSet.contains(c)) {set.add(c);MyfirstSet.put(c, set);return;}// c为非终结符 处理其每条产生式for (String s5 : list) {// c 推出空串 直接添加if (s5 == Character.toString('&')) {set.add('&');}// X -> Y1Y2Y3… 情况else {// 从左往右扫描生成式右部int i = 0;while (i < s5.length()) {char tn = s5.charAt(i);//先处理防止未初始化getFirst(tn);HashSet<Character> tvSet = MyfirstSet.get(tn);// 将其first集加入左部for (Character tmp : tvSet)set.add(tmp);// 若包含空串 处理下一个符号if (tvSet.contains('&'))i++;// 否则退出 处理下一个产生式elsebreak;}}}MyfirstSet.put(c, set);}@Overridepublic void getFirst(String s) {HashSet<Character> set = (MyfirstSetX.containsKey(s))? MyfirstSetX.get(s) : new HashSet<Character>();// 从左往右扫描该式int i = 0;while (i < s.length()) {char tn = s.charAt(i);HashSet<Character> tvSet = MyfirstSet.get(tn);// 将其非空 first集加入左部for (Character tmp : tvSet)if(tmp != '&')set.add(tmp);// 若包含空串 处理下一个符号if (tvSet.contains('&'))i++;// 否则结束elsebreak;// 到了尾部 即所有符号的first集都包含空串 把空串加入if (i == s.length()) {set.add('&');}}MyfirstSetX.put(s, set);}@Overridepublic void getFollow(char ch) {ArrayList<String> list = outputSet.get(ch);HashSet<Character> setA = MyfollowSet.containsKey(ch) ? MyfollowSet.get(ch) : new HashSet<Character>();//如果是开始符 添加 $if (ch == start) {setA.add('$');}//查找输入的所有产生式,确定c的后跟 终结符for (Character cha : VnSet) {ArrayList<String> l = outputSet.get(cha);for (String s : l)for (int i = 0; i < s.length(); i++)if (s.charAt(i) == ch && i + 1 < s.length() && VtSet.contains(s.charAt(i + 1)))setA.add(s.charAt(i + 1));}MyfollowSet.put(ch, setA);//处理c的每一条产生式for (String s : list) {int i = s.length() - 1;while (i >= 0 ) {char tn = s.charAt(i);//只处理非终结符if(VnSet.contains(tn)){// 都按 A->αB&  形式处理//若&不存在   followA 加入 followB//若&存在,把&的非空first集  加入followB//若&存在  且 first(&)包含空串   followA 加入 followB//若&存在if (s.length() - i - 1 > 0) {String right = s.substring(i + 1);//非空first集 加入 followBHashSet<Character> setF = null;if( right.length() == 1 && MyfirstSet.containsKey(right.charAt(0))) {setF = MyfirstSet.get(right.charAt(0));}else{if(!MyfirstSetX.containsKey(right)){HashSet<Character> set = new HashSet<Character>();MyfirstSetX.put(right, set);}setF = MyfirstSetX.get(right);}HashSet<Character> setX = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();for (Character cha : setF) {if (cha != '&') {setX.add(cha);}}MyfollowSet.put(tn, setX);// 若first(&)包含&   followA 加入 followBif(setF.contains('&')){if(tn != ch){HashSet<Character> setB = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();for (Character cha : setA) {setB.add(cha);}MyfollowSet.put(tn, setB);}}}//若&不存在   followA 加入 followBelse{// A和B相同不添加if(tn != ch){HashSet<Character> setB = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();for (Character cha : setA)setB.add(cha);MyfollowSet.put(tn, setB);}}i--;}//如果是终结符往前扫描  如 A->aaaBCDaaaa  此时&为 CDaaaaelse i--;}}}@Overridepublic void createTable() {//构造预测分析表的格式//终结符数组Object[] VtArray = VtSet.toArray();//非终结符数组Object[] VnArray = VnSet.toArray();// 预测分析表初始化table = new String[VnArray.length + 1][VtArray.length + 1];table[0][0] = "Vn/Vt";//初始化首行首列for (int i = 0; i < VtArray.length; i++)table[0][i + 1] = (VtArray[i].toString().charAt(0) == '&') ? "$" : VtArray[i].toString();for (int i = 0; i < VnArray.length; i++)table[i + 1][0] = VnArray[i] + "";//全部置errorfor (int i = 0; i < VnArray.length; i++)for (int j = 0; j < VtArray.length; j++)table[i + 1][j + 1] = "error";//插入生成式for (char A : VnSet) {ArrayList<String> l = outputSet.get(A);for(String s : l){HashSet<Character> set = MyfirstSetX.get(s);for (char a : set)insert(A, a, s);if(set.contains('&'))  {//如果包含&HashSet<Character> setFollow = MyfollowSet.get(A);if(setFollow.contains('$'))//判断follow集中是否包含$insert(A, '$', s);for (char b : setFollow)insert(A, b, s);}}}}@Overridepublic void analyzeLL() {System.out.println("-------------------1.LL分析过程-------------------");System.out.println("|               分析栈        输入串     动作|  ");MyAnaStatck.push('$');MyAnaStatck.push('S');displayLL();//调用分析过程方法char X = MyAnaStatck.peek();while (X != '$') {char a = strInput.charAt(Index);if (X == a) {MyAction = "match " + MyAnaStatck.peek();MyAnaStatck.pop();Index++;} else if (VtSet.contains(X))return;else if (find(X, a).equals("error"))return;else if (find(X, a).equals("&")) {MyAnaStatck.pop();MyAction = X + "->&";} else {String str = find(X, a);if (str != "") {MyAction = X + "->" + str;MyAnaStatck.pop();int len = str.length();for (int i = len - 1; i >= 0; i--)MyAnaStatck.push(str.charAt(i));} else {System.out.println("error at '" + strInput.charAt(Index) + " in " + Index);return;}}X = MyAnaStatck.peek();displayLL();}System.out.println("LL(1)文法分析成功!");System.out.println("-------------------LL分析过程-------------------");}@Overridepublic String find(char X, char a) {for (int i = 0; i < VnSet.size() + 1; i++) {if (table[i][0].charAt(0) == X)for (int j = 0; j < VtSet.size() + 1; j++) {if (table[0][j].charAt(0) == a)return table[i][j];}}return "";}@Overridepublic void insert(char X, char a, String s) {//插入if(a == '&')a = '$';for (int i = 0; i < VnSet.size() + 1; i++) {if (table[i][0].charAt(0) == X)for (int j = 0; j < VtSet.size() + 1; j++) {if (table[0][j].charAt(0) == a){table[i][j] = s;return;}}}}@Overridepublic void displayLL() {// 对输入串(a,a)$ 输出 LL(1)分析过程Stack<Character> s = MyAnaStatck;System.out.printf("%23s", s );//输出第一列:分析栈System.out.printf("%13s", strInput.substring(Index));//输出第二列:输入串System.out.printf("%10s", MyAction);//输出第三列:动作System.out.println();}@Overridepublic void ouput() {// 输出终结符的first集System.out.println("-------------------2.first集-------------------");for (Character c : VnSet) {HashSet<Character> set = MyfirstSet.get(c);System.out.printf("%10s",c + "  ->   ");for (Character cha : set)System.out.print(cha+" ");System.out.println();}System.out.println("-------------------first集-------------------");// 输出任意符号串的first集System.out.println("-------------------firstX集-------------------");Set<String> setStr =  MyfirstSetX.keySet();for (String s : setStr) {HashSet<Character> set = MyfirstSetX.get(s);System.out.printf("%10s",s + "  ->   ");for (Character cha : set)System.out.print(cha+" ");System.out.println();}System.out.println("-------------------firstX集-------------------");// 输出follow集System.out.println("-------------------3.follow集-------------------");for (Character c : VnSet) {HashSet<Character> set = MyfollowSet.get(c);System.out.print("Follow " + c + " : ");for (Character cha : set)System.out.print(cha+" ");System.out.println();}System.out.println("-------------------follow集-------------------");//构造LL1文法预测分析表System.out.println("-------------------4.LL1预测分析表-------------------");for (int i = 0; i < VnSet.size() + 1; i++) {for (int j = 0; j < VtSet.size() + 1; j++) {System.out.printf("%8s", table[i][j] + " ");}System.out.println();}System.out.println("-------------------LL1预测分析表-------------------");}
}

四、结果分析

1、输入正确的源程序截图:
将符号ε替换为&

输出结果截图:



2、输入错误的源程序截图:
输入错误文法

输出结果截图:

3、总结(自己的心得体会、你编写的语法分析程序的优缺点)
S->a|^|(T)
T->SU
U->,SU|ε

  • 优点:文法分析过程比较详细,任务整个完成过程是充实的,这个实验报告相当于对编译原理理论课的一次实践尝试,能收获很多课堂上面学不到的知识,同时也能巩固老师所教授的知识。

  • 缺点:在写程序的时候,卡在了空串那个点。最开始尝试直接在程序中定义文法时,ε能在程序中分析成功。后来在用读入文件的方式定义文法时,控制台出现乱码,这个点解决起来花了一点时间,最后决定将符号ε替换为&,程序才能运行成功。

编译原理:语法分析器相关推荐

  1. 编译原理——语法分析器(SLR)

    编译原理--语法分析器(SLR) 识别语法结构: 变量声明(不含变量初始化) if单条件分支语句以及if else 双条件分支语句 for循环和while循环语句 赋值语句 ,四则运算,逻辑判断复合语 ...

  2. 编译原理-语法分析器设计

    文章目录 语法分析器设计 实验环境 实验目的 实验内容及要求 实验步骤 用上下文无关文法表达 改写为LL(1)文法 First集与Follow集 预测分析表 结果分析 源代码 语法分析器设计 实验环境 ...

  3. 编译原理—语法分析器(Java)

    递归下降语法分析 1. 语法成分说明 <语句块> ::= begin<语句串> end <语句串> ::= <语句>{:<语句>} < ...

  4. 编译原理------语法分析器C/C++代码实现

    一.实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. 二.实验内容 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. 2.1 待分析的简单语言的语 ...

  5. 编译原理语法分析器实验报告

    编号: 实习 一 二 三 四 五 六 七 八 九 十 总评 教师签名 成绩 第一部分 语言语法规则 Mini语言包含程序设计所需要的最基本语言成分,包括 程序定义语句 :以 program 开头 en ...

  6. 编译原理——语法分析器(C/C++代码实现)

    0

  7. 编译原理—语法制导翻译、S属性、L属性、自上而下、自下而上计算

    编译原理-语法制导翻译.S属性.L属性.自上而下.自下而上计算 1.语法制导翻译 1.1属性文法 1.2算术表达式的计数器 1.3属性的分类 1.4属性依赖图 继承属性的计算 1.5语义规则的计算方法 ...

  8. 编译原理算符分析器实现 -* c语言代码,编译原理论文-词法分析器的设计与实现...

    <编译原理论文-词法分析器的设计与实现>由会员分享,可在线阅读,更多相关<编译原理论文-词法分析器的设计与实现(13页珍藏版)>请在人人文库网上搜索. 1.编译原理论文题 目 ...

  9. 编译原理 -- 语法制导翻译

    语法制导翻译 语法制导翻译是通过向一个文法的产生式附加一些规则或程序片段而得到的. 语法制导翻译的两个概念 下面是与语法制导翻译相关的两个概念: 属性(attribute) : 表示与某个程序构造相关 ...

  10. 编译原理算符分析器实现 -* c语言代码,C语言实现算符优先文法源代码(编译原理)...

    下面教大家用C语言实现编译原理中的算符优先文法.求出FIRSTVT集和LASTVT集,并判断该文法是否是算符优先文法. 一.知识解析 1.定义 算符优先文法是一种自下而上的分析方法,其文法的特点是文法 ...

最新文章

  1. python snmp 交换机 配置文件_编译安装SNMP,snmpd.conf配置文件说明
  2. 9号团队-团队任务4:每日立会(2018-11-26,2018-11-27)
  3. html万年历闹钟怎么取消,万年历如何取消整点报时,他上面有四个键,分...
  4. ffmpeg加环境变量
  5. Perl中的正则表达式
  6. c++ 23种设计模式_使用Go实现GoF的23种设计模式(三)
  7. mysql win linux性能对比,不同系统上 MySQL 的性能对比
  8. Altium AD20的PCB板框绘制、定义板子形状、重新设置原点、放置尺寸标注
  9. 侧信道攻击之模板攻击
  10. 计算机图形学-五角星的画法(转)
  11. 报The requested URL / was not found on thisserver. 网站打开出现404
  12. android 4.4 红外,RTK2969平台android4.4添加新红外遥控器(一)
  13. 计算机毕业设计-基于微信小程序的大学生心理预约咨询系统-心理测试小程序
  14. 【机器人学】3-RUU-delta并联机器人正运动学、逆运动学和微分运动学
  15. 用r语言画出y = ax^2 + bx + c,R语言中如何使用最小二乘法
  16. 磁珠和电感有什么不同?
  17. 在“双减”政策下,利用《陈老师排课12.0》排主课、早自习、课后服务三种不同时段的综合课表
  18. 【专业的图像后期处理软件】飞思 Capture One 12.1 for Mac
  19. 05.第二章 抽样分布及若干预备知识(4)
  20. MySQL的进阶操作

热门文章

  1. Nero刻录软件超级实用技巧大搜罗
  2. 大专计算机论文什么方向,大专计算机论文
  3. ubuntu18字符终端不支持中文问题(汉字菱形)
  4. ShadowGun shader 解析(1)
  5. 后台经验分享:如何做权限管理系统设计?
  6. 联想台式机进入修复计算机,联想台式机一键恢复的使用方法
  7. linux多级菜单脚本教程,Linux下使用readline库编程实现多级CLI菜单
  8. 浅谈未来计算机操作系统的发展方向,浅谈未来计算机操作系统的发展方向
  9. jconsole远程连接的使用
  10. PowerDesigner下载、安装配置