编译原理实验2(2)——自下而上语法分析器

一、实验目的

1、为初等函数运算语言构造LR语法分析器。

2、掌握LR语法分析器的方法,加深对自上而下语法分析原理的理解。

3、掌握设计、编制并调试LR语法分析程序的思想和方法。

二、实验内容

一、根据初等函数运算语言运算法则,将语法模式用上下文无关文法表达。(纸上作业)

1、注意运算的优先级问题,避免产生二义性文法。

二、将上述文法改写为SLR文法。(纸上作业)

三、根据SLR文法给出预测分析表。(纸上作业)

四、根据预测分析表,给出解析SLR文法的递归下降子程序或预测分析器程序。

五、本语法分析程序的输入是实验一生成的记号流;本程序需定义语法树的数据结构;语法分析的输出是一棵语法树。

六、当输入存在语法错误时,需给出语法错误的提示,指出语法错误发生的位置和错误类型。

三、上下文无关文法

四、SLR扩广文法

五、移进规约分析表

六、实验结果

程序运行结果如下:

(实验编写、运行平台为IDEA)

七、词法分析程序主要代码

源程序关键函数代码如下:

打印树结构的驱动器代码:

//驱动器
    private static void drivers2(){
        //语句切分
        String []allSentence = outBuffer.split("\n");
        for (int jj = 0;jj<allSentence.length;jj++){
            System.out.println("记号流:"+ allSentence[jj]);
            Stack<String> stack = new Stack<>();
            //初始化栈
            stack.push("#");
            stack.push("0");
            //当前输入记号流
            String tempBuffer = allSentence[jj] + "#";
            String[] tokenBuffer = tempBuffer.split(" ");
            //初始化所有叶子
            List<TreeNode> nodes = new ArrayList<TreeNode>();
            int id = 0;
            for(int i =0 ;i<tokenBuffer.length;i++){
                TreeNode temp = new TreeNode(id,tokenBuffer[i]);
                nodes.add(temp);
            }
            //初始化树
            TreeUtils tree = new TreeUtils();
            String topNode;
            int ip = 0;
            String[] tempSentence;
            String current;
            String nextSentence;
            TreeNode startNode = new TreeNode(0,"F");
            while (ip<tokenBuffer.length && !stack.empty()) {
                current = tokenBuffer[ip];
                if (names.contains(current)){
                    current = "V";
                }
                if(current.charAt(0)>='0'&&current.charAt(0)<='9'){
                    current = "N";
                }
                if(current.charAt(0)=='-' && current.length()>1){
                    current = "N";
                }
                if(current=="PI"||current=="E"){
                    current = "k";
                }
                if (current == "sin"||current == "cos"||current == "tg"||current == "ctg"||current ==  "lg"||current == "ln"){
                    current = "t";
                }
                int status = Integer.parseInt(stack.pop());
                String nextChar = tokenBuffer[ip];
                int lie = symbolSet2.get(nextChar);
                if(predictsheet2[status][lie].charAt(0)=='s') {
                    stack.push(tokenBuffer[ip]);
                    stack.push(predictsheet2[status][lie].substring(1));
                }else if(predictsheet2[status][lie].charAt(0)=='r'){
                    int product = Integer.parseInt(predictsheet2[status][lie].substring(1));
                    int number = granum[product];
                    String replace = graleft[product];
                    List<TreeNode> tempNodes = new ArrayList<TreeNode>();
                    for(int i = 0;i<product;i++){
                        String currenceTop = stack.pop();
                        for(int j= 0;j<nodes.size();j++){
                            if(currenceTop==nodes.get(j).name){
                                tempNodes.add(nodes.get(j));
                                nodes.remove(nodes.get(j));
                                break;
                            }
                        }
                    }
                    TreeNode father = new TreeNode(id,replace);
                    father.sonList = tempNodes;
                    nodes.add(father);
                    stack.push(replace);
                    lie = symbolSet2.get(replace);
                    stack.push(predictsheet2[status][lie]);
                }else if(predictsheet2[status][lie]=="acc"){
                    startNode = nodes.get(0);
                }
                else {
                    System.out.println(current + "erro");
                    break;
                }
            }
            if(startNode!=null){
                System.out.println("success");
                System.out.println("其树结构为:");
                System.out.println("---"      //打印空格 和结点id,name
                        +"<"+startNode.id+">" + startNode.name);
                tree.queryAll(startNode,1);
            }
        }
    }

八、实验心得

在实验中消除了左递归,提取了公共左因子,构造了SLR文法,与LL(1)相比,SLR更简洁易懂,直接根据移进归约表进行选择即可,逻辑清晰。但从工作量上看,LL(1)文法比较简单,SLR在真正去用代码实现和分析的时候要耗费时间。

实验中要求打印语法树,对于此部分我并不是很了解,由于之前没有用过java来创建可视化语法树的做法,所以我上网查阅了Java树结构的相关资料和代码、项目,并且结合了C++的LR语法分析器打印树的过程,遇见了困难还咨询了学长,最终完成了打印语法树的目的,虽然语法树的结构还并不是很直观,但是可以很好地展现出语法结构。

构造移进规约分析表也是本次实验的重点之一。在转换ACTION动作表的过程中,不仅要考虑存储表的结构,还需要考虑到First集、Follow集等数据。而生成GOTO动作表的过程简单于ACTION表,只要根据输入的非终结符查看对应的转移状态即可。通过对这部分的学习的实践,我更加清楚了构造移进归约表的实现过程。

本次实验加深了我对语法分析整体流程的认识,并对其个中概念有了具象化的印象,且对其具体步骤产生了自己的思考,并融入在程序中。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
语法分析是编译原理中的重要部分,它的作用是将词法分析阶段得到的词法单元序列转换成抽象语法树(AST)或语法分析树(Parse Tree),以便于后续的语义分析、中间代码生成和目标代码生成等环节的进行。在本次实验中,我们将使用Java语言实现一个简单的语法分析器实验要求: 1. 实现自顶向下的递归下降分析器。 2. 支持的文法如下: ``` <program> ::= <stmts_list> <stmts_list> ::= <stmt> | <stmts_list> <stmt> <stmt> ::= <if_stmt> | <while_stmt> | <assign_stmt> <if_stmt> ::= if <condition> then <stmts_list> end <while_stmt> ::= while <condition> do <stmts_list> end <assign_stmt> ::= <id> = <expr> <condition> ::= <expr> <relop> <expr> <expr> ::= <term> | <expr> <addop> <term> <term> ::= <factor> | <term> <mulop> <factor> <factor> ::= <id> | <number> | '(' <expr> ')' <relop> ::= '<' | '>' | '=' | '<=' | '>=' | '<>' <addop> ::= '+' | '-' <mulop> ::= '*' | '/' <id> ::= <letter> | <id> <letter> | <id> <digit> <number> ::= <digit> | <number> <digit> <letter> ::= A | B | ... | Z | a | b | ... | z <digit> ::= 0 | 1 | ... | 9 ``` 注意:文法中的关键字 if、then、end、while、do、and 等均为保留字。 3. 实现的语法分析器应具备以下功能: - 能够识别出语法正确的程序,并输出相应的语法分析树或抽象语法树。 - 能够识别出语法错误的程序,并给出相应的错误提示信息。 - 能够处理注释和空格等无意义的字符。 4. 实验提交要求: - 实验报告,包括程序设计和实验结果分析。 - 程序源代码。 实验设计思路: 1. 根据给定的文法,设计语法分析器语法规则和对应的产生式。 2. 编写相应的Java代码,将文法转换为递归下降分析器所需要的形式。 3. 实现从输入的源代码中读取词法单元序列的功能。 4. 实现递归下降分析器的核心算法,对输入的词法单元序列进行语法分析,并构建相应的语法分析树或抽象语法树。 5. 在语法分析过程中,需要处理注释和空格等无意义的字符,以便于正确识别语法错误。 6. 在语法分析过程中,需要对输入的源代码进行错误检查,并给出相应的错误提示信息。 7. 输出语法分析树或抽象语法树,以便于后续的语义分析、中间代码生成和目标代码生成等环节的进行。 实验结果分析: 经过实验测试,我们的语法分析器能够正确地识别出合法的程序,并输出相应的语法分析树或抽象语法树。同时,它也能够正确地识别出语法错误的程序,并给出相应的错误提示信息。总的来说,本次实验取得了较好的实验效果。 实验源代码: 见下方代码框:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neymessi_JR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值