编译原理实验——不同进制间四则运算计算器

一、实验目的

1、实现一个词法分析程序,将输入字符串流分解成单词流供语法分析使用。(注意:如果单词输入错误,必须有提示)
2、在词法分析的基础上实现一个语法分析程序,对词法分析的结果进行语法分析。
3、在语法分析的基础上实现一个语义分析程序,求出输入算式的最后结果。

二、文法

算术运算文法如下:
(1) E->E+E
(2) E->E-E
(3) E->E
E
(4) E->E/E
(5) E->(E)
(6) E->i
(7) i->十进制整数|十进制小数|八进制整数|十进制小数|十六进制整数|十六进制小数
(8) 十进制小数->(0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)).(0|1|2|3|4
|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)

(9)八进制小数->0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7).(0|1|2|3|4|5|6|7)(0
|1|2|3|4|5|6|7)

(10) 十六进制小数 ->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8
|9|a|b|c|d|e|f).(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)
(11) 十进制整数->0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*
(12) 八进制整数-> 0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*
(13) 十六进制整数->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8
|9|a|b|c|d|e|f)**

单词分类
运算符:+ - * / ( )
常数:十进制小数、十进制整数、十六进制小数、十六进制整数、八进制小数、八进制整数

三、识别不同进制单词的DFA自动机

编译原理实验——不同进制间四则运算计算器_第1张图片

四、代码

1、State类

public class State {

    char name;
    double value;
    int decimal;
    String type;

    public State(char name, double value, int decimal, String type) {
        this.name = name;
        this.value = value;
        this.decimal = decimal;
        this.type = type;
    }

    public char getName() {
        return name;
    }

    public void setName(char name) {
        this.name = name;
    }

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public int getDecimal() {
        return decimal;
    }

    public void setDecimal(int decimal) {
        this.decimal = decimal;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

}

2、IsOperator类

public final class IsOperator {
    public static final char[] TOKEN=new char[]{'+','-','*','/','(',')'};
    
    /*判断是否是运算符*/
    public static boolean isPulsSign(char token){
        if((token=='+')||(token=='-')||(token=='*')||(token=='/')||(token=='(')||(token==')')){
            return true;
        }else return false;
    }
    
}

3、Attribute类

public class Attribute {
    char ch;
    double val;

    public Attribute(char ch, double val) {
        this.ch = ch;
        this.val = val;
    }

    public Attribute() {
    }

   
    public char getCh() {
        return ch;
    }

    public void setCh(char ch) {
        this.ch = ch;
    }

    public double getVal() {
        return val;
    }

    public void setVal(double val) {
        this.val = val;
    }

    
}

4、NumberDfa类

public final class NumberDfa {

    public static final char[] STATE = new char[]{'X', 'Y', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'};//自动机的状态
    public static final char[] TOKEN = new char[]{'.', 'x', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'};//输入的字符
    public static final char S_START = 'X';//开始状态
    public static final char[] S_END = new char[]{'M', 'Y', 'P', 'Q', 'U', 'V', 'W'};//终结状态

    /*根据DFA状态转换图,进行各状态的转换*/
    public static State tranState(State state, char token) {
        if (state.name == 'X') {
            if (token == '0') {
                return new State('Y', state.value * 10 + (token - 48), 0, "十进制整数");
            } else if (token >= '1' && token <= '9') {
                return new State('M', state.value * 10 + (token - 48), 0, "十进制整数");
            } else {
                return null;
            }
        } else if (state.name == 'M') {
            if (token >= '0' && token <= '9') {
                return new State('M', state.value * 10 + (token - 48), 0, "十进制整数");
            } else if (token == '.') {
                return new State('R', state.value, 0, null);
            } else {
                return null;
            }
        } else if (state.name == 'R') {
            if (token >= '0' && token <= '9') {
                return new State('U', state.value + (token - 48) / pow(10, state.decimal + 1), state.decimal + 1, "十进制小数");
            } else {
                return null;
            }
        } else if (state.name == 'U') {
            if (token >= '0' && token <= '9') {
                return new State('U', state.value + (token - 48) / pow(10, state.decimal + 1), state.decimal + 1, "十进制小数");
            } else {
                return null;
            }
        } else if (state.name == 'Y') {
            if (token == '.') {
                return new State('R', state.value, 0, null);
            } else if (token >= '0' && token <= '7') {
                return new State('P', state.value * 8 + (token - 48), 0, "八进制整数");
            } else if (token == 'x' || token == 'X') {
                return new State('N', state.value, 0, null);
            } else {
                return null;
            }
        } else if (state.name == 'P') {
            if (token >= '0' && token <= '7') {
                return new State('P', state.value * 8 + (token - 48), 0, "八进制整数");
            } else if (token == '.') {
                return new State('S', state.value, 0, null);
            } else {
                return null;
            }
        } else if (state.name == 'S') {
            if (token >= '0' && token <= '7') {
                return new State('V', state.value + (token - 48) / pow(8, state.decimal + 1), state.decimal + 1, "八进制小数");
            } else {
                return null;
            }
        } else if (state.name == 'V') {
            if (token >= '0' && token <= '7') {
                return new State('V', state.value + (token - 48) / pow(8, state.decimal + 1), state.decimal + 1, "八进制小数");
            } else {
                return null;
            }
        } else if (state.name == 'N') {
            if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
                return new State('Q', (token >= '0' && token <= '9') ? state.value * 16 + (token - 48) : ((token >= 'a' && token <= 'f') ? state.value * 16 + (token - 87) : state.value * 16 + (token - 55)), 0, "十六进制整数");
            } else {
                return null;
            }
        } else if (state.name == 'Q') {
            if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
                return new State('Q', (token >= '0' && token <= '9') ? state.value * 16 + (token - 48) : ((token >= 'a' && token <= 'f') ? state.value * 16 + (token - 87) : state.value * 16 + (token - 55)), 0, "十六进制整数");
            } else if (token == '.') {
                return new State('T', state.value, 0, null);
            } else {
                return null;
            }
        } else if (state.name == 'T') {
            if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
                return new State('W', (token >= '0' && token <= '9') ? state.value + (token - 48) / pow(16, state.decimal + 1) : ((token >= 'a' && token <= 'f') ? state.value + (token - 87) / pow(16, state.decimal + 1) : state.value + (token - 55) / pow(16, state.decimal + 1)), state.decimal + 1, "十六进制小数");
            } else {
                return null;
            }
        } else if (state.name == 'W') {
            if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
                return new State('W', (token >= '0' && token <= '9') ? state.value + (token - 48) / pow(16, state.decimal + 1) : ((token >= 'a' && token <= 'f') ? state.value + (token - 87) / pow(16, state.decimal + 1) : state.value + (token - 55) / pow(16, state.decimal + 1)), state.decimal + 1, "十六进制小数");
            } else {
                return null;
            }
        }
        return null;
    }

    /*用于输出词法分析的结果*/
    public static boolean estimation(char[] token) {
        System.out.println("词法分析的结果为:");
        boolean flag=true;
        if (token != null && token.length != 0) {
            State state = new State(S_START, 0.0, 0, null);
            ArrayList<Character> ss = new ArrayList<>();
            for (int i = 0; i < token.length; i++) {
                if (!IsOperator.isPulsSign(token[i])) {
                    state = tranState(state, token[i]);
                    ss.add(token[i]);
                } else {
                    if (state.type != null) {
                        for (Character s : ss) {
                            System.out.print(s);
                        }
                        ss.clear();
                        System.out.println( " " +state.type);
                    }
                    System.out.println(token[i] + "  运算符");
                    state = new State(S_START, 0.0, 0, null);
                }
                if (state == null) {
                    for (Character s : ss) {
                        System.out.print(s);
                    }
                    ss.clear();
                    System.out.println("  错误数据");
                    flag=false;
                    state = new State(S_START, 0.0, 0, null);
                }
            }
            for (Character s : ss) {
                System.out.print(s);
            }
            ss.clear();
            System.out.println( " "+state.type);
        }
        return flag;
    }
    
    /*用于将输入的算数表达式转换成相应的句子,并存入相应的属性值(即转换完成后的十进制数),为后面的语法分析和语义分析做准备*/
    public static List<Attribute> getAttribute(char token[]){
        ArrayList<Attribute> att=new ArrayList<>();
        if (token != null && token.length != 0) {
            State state = new State(S_START, 0.0, 0, null);
            for (int i = 0; i < token.length; i++) {
                if (!IsOperator.isPulsSign(token[i])) {
                    state = tranState(state, token[i]);
                } else {
                    if (state.type != null) {
                        att.add(new Attribute('i',state.value));
                    }
                    att.add(new Attribute(token[i],0));
                    state = new State(S_START, 0.0, 0, null);
                }
                if (state == null) {
                    state = new State(S_START, 0.0, 0, null);
                }
            }
            att.add(new Attribute('i',state.value));
        }
        return att;
    }
}

5、OperatorPrecedence类,采用算符优先分析法

public class OperatorPrecedence {

    //算符优先关系表
    public static final char[][] priorityTable = {
        {'>', '>', '<', '<', '<', '>', '<', '>'},
        {'>', '>', '<', '<', '<', '>', '<', '>'},
        {'>', '>', '>', '>', '<', '>', '<', '>'},
        {'>', '>', '>', '>', '<', '>', '<', '>'},
        {'<', '<', '<', '<', '<', '=', '<', ' '},
        {'>', '>', '>', '>', ' ', '>', ' ', '>'},
        {'>', '>', '>', '>', ' ', '>', ' ', '>'},
        {'<', '<', '<', '<', '<', ' ', '<', '='}};
    public static final String[] G = {"E->E+E", "E->E-E", "E->E*E", "E->E/E", "E->(E)", "E->i"}; //文法
    public static final char[] endSign = {'+', '-', '*', '/', '(', ')', 'i', '#'};//终结符
    public static final char NotendSign = 'E';//非终结符

    //判断是否是终结符
    private static boolean isEnd(char ch) {
        for (int i = 0; i < endSign.length; i++) {
            if (endSign[i] == ch) {
                return true;
            }
        }
        return false;
    }

    private static int endPosition(char ch) {
        for (int i = 0; i < endSign.length; i++) {
            if (endSign[i] == ch) {
                return i;
            }
        }
        return -1;
    }

    //根据产生式返回右部分的左边部分
    public static char retLeft(String str) {
        for (int i = 0; i < G.length; i++) {
            StringBuffer a = new StringBuffer();
            for (int j = 3; j < G[i].length(); j++) {
                a.append(G[i].charAt(j));
            }
            if (str.equals(a.toString())) {
                return G[i].charAt(0);
            }
        }
        return 0;
    }

    public void Analysis(List<Attribute> att) {
        int status = 0;//0是移进1是规约
        int count = 0;//步骤数
        int k = 0;//栈的深度
        int j = 0;
        int step = 0;
        String gyStr = null;//规约字符串
        System.out.println("语法分析结果为:");
        att.add(new Attribute('#', 0));
        String sentence = "";
        for (Attribute a : att) {
            sentence = sentence + a.ch;
        }
        ArrayList<Attribute> Stack = new ArrayList<>();//栈
        System.out.printf("%-7s%-13s%-7s%-9s%-8s\n", "步骤", "栈", "a读入", "剩余串", "操作");
        Stack.add(new Attribute('#', 0));//栈的初始为#
        Attribute a = att.get(step++);//获取当前输入的字符
        while (Stack.size() != 2 || a.ch != '#') {

            if (status == 0) {
                if (count != 0) {
                    String str = "";
                    for (int i = 0; i < Stack.size(); i++) {
                        str = str + Stack.get(i).ch;
                    }
                    System.out.printf("  %-8s\n %-8d%-15s%-8c%-10s", "移进", count, str, a.ch, sentence.substring(step));
                } else {
                    String str = "";
                    for (int i = 0; i < Stack.size(); i++) {
                        str = str + Stack.get(i).ch;
                    }
                    System.out.printf(" %-8d%-15s%-8c%-10s", count, str, a.ch, sentence.substring(step));
                }
            }
            //System.out.println(k);
            char ch = Stack.get(k).ch;
            if (isEnd(ch)) {
                j = k;
            } else if (j >= 1) {
                j = k - 1;
            }
            //归约
            char temp = 0;
            if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '>') {
                ArrayList<Attribute> judge = new ArrayList<>();
                temp = Stack.get(j).ch;
                if (isEnd(Stack.get(j - 1).ch)) {
                    j = j - 1;
                } else {
                    j = j - 2;
                }
                while (priorityTable[endPosition(Stack.get(j).ch)][endPosition(temp)] == '>' || priorityTable[endPosition(Stack.get(j).ch)][endPosition(temp)] == '=') {
                    if (isEnd(Stack.get(j - 1).ch)) {
                        j = j - 1;
                    } else {
                        j = j - 2;
                    }
                }
                for (int i = j + 1; i < Stack.size(); i++) {
                    judge.add(Stack.get(i));
                }

                int t = Stack.size();
                for (int i = j + 1; i < t; i++) {
                    Stack.remove(j + 1);
                }

                String judgeStr = "";
                for (Attribute ju : judge) {
                    judgeStr = judgeStr + ju.ch;
                }
                char res = retLeft(judgeStr);
                if (res != 0) {
                    count++;
                    k = j + 1;
                    //Stack.add(res);
                    if (judge.size() == 1) {
                        Stack.add(new Attribute(res, judge.get(0).val));
                    } else if(judge.get(0).ch=='('&&judge.get(2).ch==')'){
                        Stack.add(new Attribute(res, judge.get(1).val));
                    }else {
                        if (judge.get(1).ch == '+') {
                            Stack.add(new Attribute(res, judge.get(0).val + judge.get(2).val));
                        } else if (judge.get(1).ch == '-') {
                            Stack.add(new Attribute(res, judge.get(0).val - judge.get(2).val));
                        } else if (judge.get(1).ch == '*') {
                            Stack.add(new Attribute(res, judge.get(0).val * judge.get(2).val));
                        } else if (judge.get(1).ch == '/') {
                            Stack.add(new Attribute(res, judge.get(0).val / judge.get(2).val));
                        }
                    }
                    status = 1;
                    gyStr = "用" + res + "->" + judgeStr + "规约";
                    String str = "";
                    for (int i = 0; i < Stack.size(); i++) {
                        str = str + Stack.get(i).ch;
                    }
                    System.out.printf("  %-8s\n %-8d%-15s%-8c%-10s", gyStr, count, str, a.ch, sentence.substring(step));
                }
            }
            //移进
            if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '<' || priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '=') {
                count++;
                k++;
                status = 0;
                Stack.add(a);
            } else if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == ' ') {
                System.out.print("读入单词出错!");
                return;
            }

            if (status == 0 && step < sentence.length()) {
                a = att.get(step++);
            }
            if (Stack.size() == 3 && a.ch == '#') {
                break;
            }
        }
        System.out.printf("%-8s\n", "接受");
        System.out.println("最终结果:"+Stack.get(1).val);
    }
}

参考代码:https://blog.csdn.net/tiandc/article/details/103372651?utm_source=app

6、

public class Test {

    public static void main(String[] args) {
        System.out.print("请输入四则运算的算数运算式:");
        Scanner input = new Scanner(System.in);
        String str = input.next();
        char ss[] = str.toCharArray();
        System.out.println();
        boolean flag = true;
        if (!estimation(ss)) {
            System.out.println("单词出现错误,不能进行语法分析!");
            flag = false;
        }
        if (flag) {
            boolean flagg = true;
            for (Attribute a : getAttribute(ss)) {
                if (flagg) {
                    System.out.println();
                    System.out.print("该算数运算式对应的句子:");
                    flagg = false;
                }
                System.out.print(a.ch);
            }
            System.out.println();
            OperatorPrecedence op = new OperatorPrecedence();
            op.Analysis(getAttribute(ss));
        }
    }
}

五、运行结果
编译原理实验——不同进制间四则运算计算器_第2张图片
编译原理实验——不同进制间四则运算计算器_第3张图片

编译原理实验——不同进制间四则运算计算器_第4张图片

你可能感兴趣的:(java)