实验二 语法分析之LR(0)分析

LR 分析器(自动机)结构

LR自动机

例子

文法:
G(E):
E->aA|bB
A->cA|d
B–>cB|d
要求:
(1)构造LR(0)项目集规范簇。
(2)构造LR(0)分析表。
(3)LR(0)分析过程(移进、规约、接受、报错)的实现。输入一个符号串,依据LR(0)分析表,以表格形式输出分析过程。
程序测试:
(1)输入:bcd#
(2)输入:acccccd#
(3)输入:acccddd#

LR(0) 分析表

在这里插入图片描述

LR(0)项目集规范簇

在这里插入图片描述
在这里插入图片描述

代码

import java.util.*;

/**
 * LR(0) 分析
 * G(E):
 * E->aA|bB
 * A->cA|d
 * B-->cB|d
 * @author ymj
 * @Date: 2020/6/7 11:01
 */
public class LRAnalysis {

    public static Scanner cin = new Scanner(System.in);

    /** LR(0)分析表 */
    private static  Map<Character, String>[] LRTable;

    /** G(E) */
    private static  String[][] G;

    /** 状态栈*/
    private static Stack<Integer> statusStack ;

    /** 符号栈*/
    private static Stack<Character> symbolStack;

    /** 构造 LR(0) 表 */
    public static void initLRTable() {
        LRTable = new HashMap[12];
        for (int i= 0; i < LRTable.length; i++) {
            LRTable[i] = new HashMap<>(6);
        }
        LRTable[0].put('a', "s2"); LRTable[0].put('b', "s3"); LRTable[0].put('E', "1");
        LRTable[1].put('$', "acc");
        LRTable[2].put('c', "s5");LRTable[2].put('d', "s6");LRTable[2].put('A', "4");
        LRTable[3].put('c', "s8");LRTable[3].put('d', "s9");LRTable[3].put('B', "7");
        LRTable[4].put('a', "r1");LRTable[4].put('b', "r1");LRTable[4].put('c', "r1");LRTable[4].put('d', "r1");LRTable[4].put('$', "r1");
        LRTable[5].put('c', "s5");LRTable[5].put('d', "s6");LRTable[5].put('A', "10");
        LRTable[6].put('a', "r4");LRTable[6].put('b', "r4");LRTable[6].put('c', "r4");LRTable[6].put('d', "r4");LRTable[6].put('$', "r4");
        LRTable[7].put('a', "r2");LRTable[7].put('b', "r2");LRTable[7].put('c', "r2");LRTable[7].put('d', "r2");LRTable[7].put('$', "r2");
        LRTable[8].put('c', "s8");LRTable[8].put('d', "s9");LRTable[8].put('B', "11");
        LRTable[9].put('a', "r6");LRTable[9].put('b', "r6");LRTable[9].put('c', "r6");LRTable[9].put('d', "r6");LRTable[9].put('$', "r6");
        LRTable[10].put('a', "r3");LRTable[10].put('b', "r3");LRTable[10].put('c', "r3");LRTable[10].put('d', "r3");LRTable[10].put('$', "r3");
        LRTable[11].put('a', "r5");LRTable[11].put('b', "r5");LRTable[11].put('c', "r5");LRTable[11].put('d', "r5");LRTable[11].put('$', "r5");

        G = new String[][]{
                {"S", "E"},
                {"E", "aA"},
                {"E", "bB"},
                {"A", "cA"},
                {"A", "d"},
                {"B", "cB"},
                {"B", "d"}
        };

        int[][] arr1 = {{1,2}, {2, 3}, {4, 5}};


    }

    public static void printTable(int p, String input, String action) {
        String status = "";
        for (int temp: statusStack) {
            status += temp + "";
        }
        String symbol = "";
        for (char temp: symbolStack) {
            symbol += temp + "";
        }

        String in = "";
        for (int i = p; i < input.length(); i++){
            in += input.charAt(i) + "";
        }
        System.out.printf("%8s\t %8s\t %8s\t %s\n",status, symbol, in, action);

    }

    public static boolean LR0Analysis(String input) {
        System.out.println(input);
        System.out.printf("%8s\t %8s\t %8s\t\n","状态栈", "符号栈", "输入串");
        statusStack.push(0);
        symbolStack.push('$');
        int p = 0;

        while(true) {

            int status = statusStack.peek(); // 状态
            char nextChar = input.charAt(p); // 输入字符
            int nextStatus = -1;
            if (LRTable[status].containsKey(nextChar)) {
                String info = LRTable[status].get(nextChar);
                printTable(p, input, info);
                if (info.equals("acc")) {
                    break;
                }
                if (info.charAt(0) == 's') { // 移进状态
                    nextStatus = Integer.parseInt(info.substring(1));
                    statusStack.push(nextStatus);
                    symbolStack.push(nextChar);
                    p++;
                } else if (info.charAt(0) == 'r') { // 规约状态
                    nextStatus = Integer.parseInt(info.substring(1));
                    for (int i = 0; i < G[nextStatus][1].length(); i++) {
                        symbolStack.pop();
                        statusStack.pop();
                    }
                    char temp = G[nextStatus][0].charAt(0);
                    symbolStack.push(temp);
                    int s = statusStack.peek();
                    statusStack.push(Integer.parseInt(LRTable[s].get(temp)));
                } else { // GOTO 转移
                    break;
                }

            } else {
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {

        initLRTable();

        while (true) {
            String string = cin.nextLine();
            statusStack = new Stack<>();
            symbolStack = new Stack<>();
            if (string.equalsIgnoreCase("#")) {
                System.out.println("====结束====");
                break;
            } else {
                if (LR0Analysis(string.trim()+ "$" )) {
                    System.out.println("成功" + string + "是该文法的句子");
                } else {
                    System.out.println("失败" + string + "不是该文法的句子");
                }
            }
        }

    }
}

  • 8
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。 2.LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。 3.LR分析器的每一步工作是由栈顶状态和现行输入符号所唯一决定的。 4.为清晰说明LR分析器实现原理和模型: LR分析器的核心部分是一张分析表。这张分析表包括两个部分,一是“动作”(ACTION)表,另一是“状态转换”(GOTO)表。他们都是二维数组。ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。显然,GOTO(s,X)定义了一个以文法符号为字母表的DFA。 每一项ACTION(s,a)所规定的动作不外是下述四种可能之一: (1)移进 把(s,a)的下一个转态s’ = GOTO(s,X)和输入符号a推进栈,下一输入符号变成现行输入符号。 (2)规约 指用某一产生式A→β 进行规约。假若β的长度为r,规约的动作是A,去除栈顶的r个项,使状态Sm-r 变成栈顶状态,然后把(Sm-r,A)的下一状态s’ = GOTO(Sm-r,A)和文法符号A推进栈。规约动作不改变现行输入符号。执行规约动作意味着β(= Xm-r+1…Xm)已呈现于栈顶而且是一个相对于A的句柄。 (3)接受 宣布分析成功,停止分析器的工作。 (4)报错 发现源程序含有错误,调用出错处理程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值