编译原理笔记之预测分析表(java实现)

1. 文法

前提是程序没有左递归符合LL(1)文法:

文法如下:

L → E;L|ε
E → TE’
E’ → +TE’|-TE’|ε
T → FT’
T’ → *FT’|/FT’|modFT’|ε
F → (E)|id|num

为了程序便于编写将E’替换为e,T’替换为t,num替换成n,mod替换成m,id替换成i

2. FIRST集合

FIRST(F)={(,i,num};
FIRST(E’)={+, -,ε};
FIRST(T)={(,i,num};
FIRST(T’)={*,/,mod,ε};
FIRST(E)={ (,i,num};

3. FALLOW集合

FOLLOW(L)={#};
FOLLOW(E)={),;};
FOLLOW(E’)={),:};
FOLLOW(T)={+,-,;,)};
FOLLOW(T’)={+,-,;,)};
FOLLOW(F)={+,-,*,/,mod,),;};

4. 预测分析表

idn+-*/m();#
EE;LE;LE;Lε
ETeTeTe
e+Te-Teεε
TFtFtFt
tεε*Ft/FtmFtεε
Fidn(E)

5. 代码实现

package com.xawl.oo;
import java.util.Scanner;
/**
 * @author qin jin
 * @date 2022/6/6 11:14
 *
 *  为了程序便于编写将E'替换为e,T'替换为t,mod替换成m,num替换成n
 */
public class GrammarMain {
    public static void main(String[] args){
        boolean isContinue = true;
        while(isContinue) {
            GrapparAnalyze analyze = new GrapparAnalyze();
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入你要翻译的表达式:");
            String inputExpression = scan.nextLine();
            inputExpression = inputExpression.replace("id","i");
            String srcdata = inputExpression.trim();
            if("".equals(srcdata) || srcdata == null) {
                System.out.println("输入表达式为空,请重新输入");
            }else {
                String result = analyze.work(srcdata);
                System.out.println(result);
                System.out.println("是否继续?y/n");
                String yn = scan.nextLine();
                if("no".equals(yn) || "n".equals(yn)) {
                    isContinue = false;
                }
            }
        }
    }
}
//自定义栈
class Stack {
    private char s[];
    private int top;
    private int base;
    private final int MAX = 200;
    /* 初始化栈 */
    public Stack() {
        initStack();
    }

    private void initStack() {
        s = new char[MAX];
        base = 0;
        top = 0;
    }

    public boolean isEmpty() {
        if(top == base) {
            return true;
        }else {
            return false;
        }
    }

    /**
     * @Description: 获取栈顶元素
     * @return 返回栈顶元素
     */
    public char getTop() {

        return s[top-1];

    }

    /**
     * @Description: 进栈方法
     * @param str 进栈的字符
     */
    public void push(String str) {
        for (int i = str.length() - 1; i >= 0; i--) {
            s[top++] = str.charAt(i);
        }
    }

    /**
     * @Description: 清空栈
     */
    public void clear() {
        top = base;
    }
    /**
     * @Description: 出栈
     * @return 栈顶元素出栈并返回出栈的元素
     */
    public char pop() {
        return s[--top];
    }

    /**
     * @Description: 返回栈中元素个数
     * @return 栈中元素个数
     */

    public int size() {
        return top;
    }

    /**
     * 打印栈里面的元素
     */
    public String toString() {
        StringBuffer tempStack = new StringBuffer();
        for (int i = 0; i < top; i++) {
            tempStack.append(s[i]);
        }
        return tempStack.toString();
    }
}

//分析器
class GrapparAnalyze {
    //分析表将E'替换为e,T'替换t,$为空
    private String tab[][] = {
            { "$",  "i",   "n",  "+",  "-",   "*",   "/",   "m",  "(",    ")",  ";", "#" },

            { "L", "E;L", "E;L", "$",  "$",   "$",   "$",   "$",  "E;L",  "$",  "$",  "ε" },

            { "E", "Te" ,  "Te", "$",   "$",  "$",   "$",   "$",  "Te",   "$",  "$",  "$"  },

            { "e",  "$" ,  "$" , "+Te", "-Te", "$",  "$",   "$",   "$",   "ε",  "ε",  "$" },

            { "T", "Ft",   "Ft",  "$",   "$",   "$", "$",   "$",  "Ft",   "$",  "$",  "$" },

            { "t",  "$",    "$",   "ε",  "ε",  "*Ft", "/Ft", "mFt", "$",  "ε",  "ε",  "$"  },

            { "F",  "i",    "n",   "$",   "$",  "$",    "$",   "$", "(E)", "$", "$", "$"  }
    };


    private String input;  //input中存放输入的表达式
    private StringBuffer tempBuffer;    //存放要输出的字符串
    private int ptr, row, col, step; //指针,预测表中的行,列,当前步骤
    private boolean symbol;
    private Stack stack;
    public GrapparAnalyze(){
        stack = new Stack();
        tempBuffer = new StringBuffer();
        symbol=true;
        input="";
        stack.clear();
        stack.push("#");
        row=1;
        ptr=0;
        step=1;
    }
    public int column(char c) {  //判断预测表中的列
        switch (c) {
            case 'i':
                return 1;
            case 'n':
                return 2;
            case '+':
                return 3;
            case '-':
                return 4;
            case '*':
                return 5;
            case '/':
                return 6;
            case 'm':
                return 7;
            case '(':
                return 8;
            case ')':
                return 9;
            case ';':
                return 10;
            case '#':
                return 11;
            default:
                return -1;
        }
    }
    public int line(char c) { //判定预测表中的行
        switch (c) {
            case 'L':
                return 1;
            case 'E':
                return 2;
            case 'e':
                return 3;
            case 'T':
                return 4 ;
            case 't':
                return 5;
            case 'F':
                return 6;
            default:
                return -1;
        }
    }

    public void show(String str) {
        tempBuffer.append(String.format("%-7d%-14s%-20s%-20s\r\n",
                step, filter(stack.toString()), filter(input.substring(ptr)), filter(str)));
        step++;
    }

    public void analyse() {
        stack.push(tab[row][0]);   //预测表中的第一个元素‘E’
        show("初始化");
        String tmp;
        char ctmp;   //栈顶元素
        while (!(input.charAt(ptr) == '#' && stack.getTop() == '#')) {
            ctmp = stack.getTop();//获取栈顶的元素
            if (input.charAt(ptr) == ctmp) { //与栈顶元素比较
                stack.pop();
                ptr++;
                show("" + ctmp + "匹配");
                continue;
            }
            //判断ptr位置的终结符所在预测表的列位置
            col = column(input.charAt(ptr));
            if (col == -1) {
                symbol = false;
                show("未定义的字符");
                ptr++;
                break;
            }

            //判断栈顶位置所在预测表的行位置
            row = line(ctmp);
            if (row == -1) {
                symbol = false;
                show("出错");
                stack.pop();
                if (input.charAt(ptr) != '#') {
                    ptr++;
                }
                continue;
            }

            tmp = tab[row][col];
            if (tmp.charAt(0) == '$') {
                symbol = false;
                show("出错");
                stack.pop();
                if (input.charAt(ptr) != '#') {
                    ptr++;
                }
            } else if (tmp.charAt(0) == 'ε') {
                stack.pop();
                show("" + ctmp + "->" + 'ε');
            } else {
                stack.pop();
                stack.push(tmp);
                show("" + ctmp + "->" + tmp);
            }
        }
    }
    //过滤方法将打印的字符串中e和t替换为E'和T'
    public String filter(String src) {
        if(src.contains("e") || src.contains("t")|| src.contains("i")|| src.contains("m")|| src.contains("n")) {
            StringBuffer result = new StringBuffer();
            char item;
            for(int i = 0;i < src.length(); i++) {
                item = src.charAt(i);
                if(item == 'e') {
                    result.append("E'");
                    continue;
                }else if(item == 't') {
                    result.append("T'");
                    continue;
                }else if(item == 'i'){
                    result.append("id");
                    continue;
                }else if(item == 'n'){
                    result.append("num");
                    continue;
                }else if(item == 'm'){
                    result.append("mod");
                    continue;
                }
                result.append(item);
            }
            return result.toString();
        }else {
            return src;
        }
    }

    public String work(String inputExpression) {
        input = inputExpression + '#';
        symbol = true;
        tempBuffer.append(String.format("%-8s%-20s%-20s%-20s\r\n",
                "步骤","分析栈","剩余输入栈","所用产生式"));
        analyse();
        if (symbol) {
            tempBuffer.append("\r是正确的符号串\r");
            return tempBuffer.toString();
        } else {
            tempBuffer.append("\r不是正确的符号串\r");
            return tempBuffer.toString();
        }
    }

    public StringBuffer getTempBuffer() {
        return tempBuffer;
    }
    public void setTempBuffer(StringBuffer tempBuffer) {
        this.tempBuffer = tempBuffer;
    }
    public Stack getStack() {
        return stack;
    }
    public void setStack(Stack stack) {
        this.stack = stack;
    }
    public String[][] getTab() {
        return tab;
    }
    public void setTab(String[][] tab) {
        this.tab = tab;
    }
    public String getInput() {
        return input;
    }
    public void setInput(String ns) {
        this.input = ns;
    }
    public int getPtr() {
        return ptr;
    }
    public void setPtr(int ptr) {
        this.ptr = ptr;
    }
    public int getRow() {
        return row;
    }
    public void setRow(int row) {
        this.row = row;
    }
    public int getCol() {
        return col;
    }
    public void setCol(int col) {
        this.col = col;
    }
    public int getStep() {
        return step;
    }
    public void setStep(int step) {
        this.step = step;
    }
    public boolean isBoo() {
        return symbol;
    }
    public void setBoo(boolean boo) {
        this.symbol = boo;
    }
}


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JAVA开发区

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

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

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

打赏作者

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

抵扣说明:

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

余额充值