编译原理实验三 LR(1)分析法

实验三 LR(1)分析法

构造 LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文 法识别的句子,了解 LR(K)分析方法是严格的从左向右扫描,和自底向上的 语法分析方法。

二、实验内容

对下列文法,用 LR(1)分析法对任意输入的符号串进行分析: (1)E-> E+T
(2)E->T
(3)T-> T*F

(4)T->F (5)F-> (E) (6)F-> i

三、LR(1)分析法实验设计思想及算法

(1)总控程序,也可以称为驱动程序。对所有的 LR 分析器总控程序都是相同的。 (2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的 LR 分析器 不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO) 表两个部分,它们都可用二维数组表示。 (3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。 分析器的动作就是由栈顶状态和当前输入符号所决定。

 LR 分析器由三个部分组成:

16

 其中:SP 为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用 GOTO[i,X]=j 表示,规定当栈顶状态为 i,遇到当前文法符号为 X 时应 转向状态 j,X 为终结符或非终结符。

 ACTION[i,a]规定了栈顶状态为 i 时遇到输入符号 a 应执行。动作有四种 可能:

(1)移进:
action[i,a]= Sj:状态 j 移入到状态栈,把 a 移入到文法符号栈,其中 i,j 表

示状态号。 (2)归约:

action[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符 A,即文 法中有 A- B 的产生式,若 B 的长度为 R(即|B|=R),则从状态栈和文法符号栈中 自顶向下去掉 R 个符号,即栈指针 SP 减去 R,并把 A 移入文法符号栈内, j=GOTO[i,A]移进状态栈,其中 i 为修改指针后的栈顶状态。
(3)接受 acc:

当归约到文法符号栈中只剩文法的开始符号 S 时,并且输入符号串已结束即 当前输入符是'#',则为分析成功。
(4)报错:

当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输 入端不是该文法能接受的符号串。

17

四、实验要求

1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。 2、如果遇到错误的表达式,应输出错误提示信息。 3、程序输入/输出实例: 输入一以#结束的符号串(包括+*()i#):在此位置输入符号串 输出过程如下:

步骤 状态栈 符号栈 剩余输入串 动作
1 0 # i+i*i# 移进

i+i*i 的 LR 分析过程

步骤

状态栈

符号栈

输入串

动作说明

1

0

#

i+i*i#

ACTION[0,i]=S5,状态 5 入栈

2

05

#i

+i*i#

r6: F→i 归约,GOTO(0,F)=3 入栈

3

03

#F

+i*i#

r4: T→F 归约,GOTO(0,T)=3 入栈

4

02

#T

+i*i#

r2: E→T 归约,GOTO(0,E)=1 入栈

18

5

01

#E

+i*i#

ACTION[1,+]=S6,状态 6 入栈

6

016

#E+

i*i#

ACTION[6,i]=S5,状态 5 入栈

7

0165

#E+i

*i#

r6: F→i 归约,GOTO(6,F)=3 入栈

8

0163

#E+F

*i#

r4: T→F 归约,GOTO(6,T)=9 入栈

9

0169

#E+T

*i#

ACTION[9,*]=S7,状态 7 入栈

10

01697

#E+T*

i#

ACTION[7,i]=S5,状态 5 入栈

11

016975

#E+T*i

#

r6:F→i 归约,GOTO(7,F)=10 入栈

12

0169710

#E+T*F

#

r3: T→T*F 归约,GOTO(6,T)=9 入栈

13

0169

#E+T

#

r1:E→E+T,GOTO(0,E)=1 入栈

14

01

#E

#

Acc:分析成功

4、输入符号串为非法符号串(或者为合法符号串)

算术表达式文法的 LR 分析表

状 态

ACTION

GOTO

i

+

*

(

)

#

E

T

F

0

S5

  

S4

  

1

2

3

1

 

S6

   

acc

   

2

 

r2

S7

 

r2

r2

   

3

 

r4

r4

 

r4

r4

   

4

S5

  

S4

  

8

2

3

5

 

r6

r6

 

r6

r6

   

6

S5

  

S4

   

9

3

7

S5

  

S4

    

10

8

 

S6

  

S11

    

9

 

r1

S7

 

r1

r1

   

10

 

r3

r3

 

r3

r3

   

11

 

r5

r5

 

r5

r5

   

五、实验步骤

1、根据流程图编写出各个模块的源程序代码上机调试。

19

2、编制好源程序后,设计若干用例对系统进行全面的上机测试,并通过所设计 的 LR(1)语法分析程序;直至能够得到完全满意的结果。
3、书写实验报告 ;实验报告正文的内容:

  •   描述 LR(1)语法分析程序的设计思想。

  •   程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数

    之间的调用关系图。

  •   详细的算法描述(程序执行流程图)。

  •   给出软件的测试方法和测试结果。
    实验总结 (设计的特点、不足、收获与体会)。

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Q3 {
    StringBuilder input = new StringBuilder();

    Deque<Integer> sStack = new LinkedList<>();
    Deque<Character> cStack = new LinkedList<>();

    void start() throws IOException {
        InputStreamReader reader = new InputStreamReader(Q2.class.getResourceAsStream("Q2"));
        for(int ch; (ch = reader.read()) != -1; ){
            input.append((char)ch);
        }

        sStack.add(0);
        cStack.add('#');

        int s = sStack.getLast();
        char a = input.charAt(0);

        while(true){
            String temp = ACTION.get(s).get(a);
            if(temp == null){
                print("ERROR");
                break;
            }else if(temp.startsWith("r")){
                print("");
                int index = Integer.parseInt(temp.substring(1));
                int length = production[index][1].length();
                while(length-- != 0){
                    sStack.removeLast(); cStack.removeLast();
                }
                cStack.add(production[index][0].charAt(0));
                if(GOTO.get(sStack.getLast()).get(cStack.getLast()) == null){
                    print("ERROR");
                    break;
                }
                s = GOTO.get(sStack.getLast()).get(cStack.getLast());
                sStack.add(s);
            }else if(temp.startsWith("S")){
                print("");
                sStack.add(Integer.parseInt(temp.substring(1)));
                s = sStack.getLast();
                cStack.add(a);
                input.deleteCharAt(0);
                a = input.charAt(0);
            }else {
                print("SUCCESS");
                break;
            }
        }
    }

    void print(String msg){
        if("ERROR".equals(msg)){
            System.out.println(msg);
        }else if("SUCCESS".equals(msg)){
            System.out.println(sStack.toString() + '\t' + cStack.toString() + '\t' + input.toString() + '\t' + msg);
        }else {
            System.out.println(sStack.toString() + '\t' + cStack.toString() + '\t' + input.toString());
        }
    }


    static List<Map<Character, String>> ACTION = new ArrayList<>();
    static List<Map<Character, Integer>> GOTO = new ArrayList<>();

    static String[][] production = null;

    public static void main(String[] args) throws IOException {
        production = new String[][] {{}, {"E", "E+T"}, {"E", "T"}, {"T", "T*F"}, {"T", "F"}, {"F", "(E)"}, {"F", "i"}};

        ACTION.add(new HashMap<Character, String>(){{ put('i', "S5"); put('(', "S4"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "S6"); put('#', "acc"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r2"); put('*', "S7"); put(')', "r2"); put('#', "r2"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r4"); put('*', "r4"); put(')', "r4"); put('#', "r4"); }});
        ACTION.add(ACTION.get(0));
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r6"); put('*', "r6"); put(')', "r6"); put('#', "r6"); }});
        ACTION.add(ACTION.get(0));
        ACTION.add(ACTION.get(0));
        ACTION.add(new HashMap<Character, String>(){{ put('+', "S6"); put(')', "S11"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r1"); put('*', "S7"); put(')', "r1"); put('#', "r1"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r3"); put('*', "r3"); put(')', "r3"); put('#', "r3"); }});
        ACTION.add(new HashMap<Character, String>(){{ put('+', "r5"); put('*', "S5"); put(')', "r5"); put('#', "r5"); }});

        GOTO.add(new HashMap<Character, Integer>(){{ put('E', 1); put('T', 2); put('F', 3); }});
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<Character, Integer>(){{ put('E', 8); put('T', 2); put('F', 3); }});
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<Character, Integer>(){{ put('T', 9); put('F', 3); }});
        GOTO.add(new HashMap<Character, Integer>(){{ put('F', 10); }});
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<>());
        GOTO.add(new HashMap<>());

        Q3 q3 = new Q3();
        q3.start();
    }
}

 

  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值