Mess_LR(0)——自下而上分析

LL(0), LR(0), SLR(1), LR(1), LALR(1)的比较

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

public class Ex5 {

    private String input;

    private String lookahead;

    private int nextIndex;

    private Stack<String> stack = new Stack<>();

    private final Map<String, String> map = new HashMap<>() {
        {
            // 匿名子类实例,中间添加静态代码块用于初始化
            // 手工录入分析表... 感觉好low...
            // Action 表格式为 <"输入符号,状态","表中状态">
            // Goto 表格式为 <"非终结符,状态", "转移后状态">
            // 《编译原理》- 陈意云 第三版 P72
            put("id,0", "s5");
            put("(,0", "s4");
            put("E,0", "1");
            put("T,0", "2");
            put("F,0", "3");
            put("+,1", "s6");
            put("$,1", "acc");
            put("+,2", "r2");
            put("*,2", "s7");
            put("),2", "r2");
            put("$,2", "r2");
            put("+,3", "r4");
            put("*,3", "r4");
            put("$,3", "r4");
            put("),3", "r4");
            put("id,4", "s5");
            put("(,4", "s4");
            put("E,4", "8");
            put("T,4", "2");
            put("F,4", "3");
            put("+,5", "r6");
            put("*,5", "r6");
            put("),5", "r6");
            put("$,5", "r6");
            put("id,6", "s5");
            put("(,6", "s4");
            put("T,6", "9");
            put("F,6", "3");
            put("F,7", "10");
            put("id,7", "s5");
            put("(,7", "s4");
            put("+,8", "s6");
            put("),8", "s11");
            put("+,9", "r1");
            put("*,9", "s7");
            put("),9", "r1");
            put("$,9", "r1");
            put("+,10", "r3");
            put("*,10", "r3");
            put("),10", "r3");
            put("$,10", "r3");
            put("+,11", "r5");
            put("*,11", "r5");
            put("),11", "r5");
            put("$,11", "r5");
        }
    };

    private final Map<String, String> reduceMap = new HashMap<>() {
        {
            // 归约表
            // <"产生式序号","非终结符,右产生式符号个数">
            put("1", "E,3");
            put("2", "E,1");
            put("3", "T,3");
            put("4", "T,1");
            put("5", "F,3");
            put("6", "F,1");
        }
    };

    public Ex5() {
        input();
        process();
    }

    private void process() {
        stack.push("0");
        String search;
        String result;

        while(true){

            search = lookahead + "," + stack.peek();    // 组装搜索串
            result = map.get(search);                   // 获得结果

            while (null == result){
                System.out.println("Error! cannot find action[" +search + "]");
                nextToken();                                // 跳过当前符号
                search = lookahead + "," + stack.peek();    // 组装搜索串
                System.out.println("try action[" + search + "]");
                result = map.get(search);                   // 获得结果
            }
            
            
            if(result.charAt(0) == 's'){
                // 移进操作
                stack.push(lookahead);                                  // 非终结符入栈
                nextToken();

                result = result.replace("s", "");   // 删除s
                stack.push(result);                                     // 状态入栈

                System.out.println("shift!");

            }else if(result.charAt(0) == 'r'){
                // 归约操作
                search = result.replace("r", "");   // 删除r,获取产生式序号
                result = reduceMap.get(search);                         // 获取非终结符和右产生式符号个数

                // 输出提示
                System.out.println("reduce according to (" + search +") Production!" );

                String nonTerminal = result.charAt(0) + "";             // 非终结符
                int popTimes = 2 *
                        Integer.parseInt(result.replace(nonTerminal+",", ""));  // 弹栈次数

                // 弹栈
                for(int i = 0; i < popTimes; i++){
                    stack.pop();
                }

                // 转移操作
                // 此时非终结符未入栈,取最上面的状态与终结符构成查询串,查询 GOTO
                search = nonTerminal + "," + stack.peek();
                result = map.get(search);

                // 非终结符以及查询到的状态入栈
                stack.push(nonTerminal);
                stack.push(result);

            }else if(result.charAt(0) == 'a'){
                // 接受操作
                System.out.println("Accept!");
                break;
            }else{
                // 错误处理
                System.out.println("Map Value Error! Exit!");
                System.exit(0);
            }
        }
    }

    public static void main(String[] args) {
        new Ex5();
    }

    public void input() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("target grammar : \n"
                + "(1)E -> E + T\n"
                + "(2)E -> T\n"
                + "(3)T -> T * F\n"
                + "(4)T -> F\n"
                + "(5)F -> (E)\n"
                + "(6)F -> id"
        );

        System.out.print("Please input a string to check:");
        input = scanner.nextLine() + "$";
        nextToken();
    }

    public void nextToken() {
        lookahead = input.charAt(nextIndex) + "";
        nextIndex++;

        if (lookahead.equals("i")) {
            lookahead = "id";
            nextIndex++;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个例子: 首先,我们需要在MySQL中创建一个表`mess_xk`来存储选课信息。打开MySQL命令行或者使用MySQL客户端,输入以下代码: ``` CREATE TABLE `mess_xk` ( `id` int(11) NOT NULL AUTO_INCREMENT, `xk_id` int(11) NOT NULL, `sc_id` int(11) NOT NULL, `xk_sc` float NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` 然后,我们需要向`mess_xk`表中插入一些数据作为测试数据。输入以下代码: ``` INSERT INTO `mess_xk` (`xk_id`, `sc_id`, `xk_sc`) VALUES (1, 1, 90), (1, 2, 80), (2, 1, 85), (2, 2, 90), (2, 3, 95), (3, 1, 75), (3, 3, 80), (4, 2, 70), (5, 1, 80), (5, 2, 85), (5, 3, 90), (5, 4, 95); ``` 接下来,我们需要创建一个存储过程来实现统计选课表中每门课程的选课人数及平均成绩的功能。打开MySQL命令行或者使用MySQL客户端,输入以下代码: ``` DELIMITER $$ CREATE PROCEDURE `course_statistics`() BEGIN DECLARE course_name CHAR(50); DECLARE total_selected INT; DECLARE avg_score FLOAT; DECLARE done INT DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT DISTINCT xk_id FROM mess_xk; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; CREATE TEMPORARY TABLE temp_table ( xk_id INT, total_selected INT, avg_score FLOAT ); OPEN cur; read_loop: LOOP FETCH cur INTO course_name; IF done THEN LEAVE read_loop; END IF; SELECT COUNT(*) INTO total_selected FROM mess_xk WHERE xk_id = course_name; SELECT AVG(xk_sc) INTO avg_score FROM mess_xk WHERE xk_id = course_name; INSERT INTO temp_table (xk_id, total_selected, avg_score) VALUES (course_name, total_selected, avg_score); END LOOP; CLOSE cur; SELECT * FROM temp_table; DROP TEMPORARY TABLE temp_table; END$$ DELIMITER ; ``` 然后,我们就可以调用这个存储过程来统计选课表中每门课程的选课人数及平均成绩了。输入以下代码: ``` CALL course_statistics(); ``` 执行之后,就会输出每门课程的选课人数及平均成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值