Diseño e implementación del analizador java-léxico (principio de compilación) (implementación del código interno del identificador)

1. Características del código interno:

Un identificador corresponde a un código interno El
mismo identificador corresponde a un código interno

2. Idea de diseño:

Estructura de hashmap basada en lenguaje java:
Inserte la descripción de la imagen aquí

3. Características del hashmap de Java:

  • Al almacenar: encontrarán la misma ubicación del depósito, se produce una colisión, porque HashMap utiliza objetos de almacenamiento de listas vinculadas (cada Map.Entry tiene un siguiente puntero), esta entrada se almacenará en la lista vinculada.

  • Al buscar: utilizará hashCode para encontrar la ubicación del depósito y luego llamará al método key.equals () para encontrar el nodo correcto en la lista vinculada. Finalmente, encuentre el objeto de valor que está buscando.

  • Reduzca la colisión: use objetos modificados finales u objetos inmutables como claves, use (Integer, String)

  • Expansión dinámica: en teoría, mientras haya suficiente memoria, es posible anotar los identificadores necesarios en todos los programas.

  • Los elementos que tienen una colisión con hash se colocarán en la lista vinculada en el mismo valor de hash

  • Eficiencia de consulta: O (1), eficiencia de inserción O (1)

4. Generador de código hash del identificador: (pertenece al método incorporado de Java)

Es decir, con 31 como peso, cada carácter es el valor ASCII del carácter, y el desbordamiento natural se utiliza para tomar el módulo de manera equivalente.

La fórmula de cálculo de hash se puede contar como s [0] * 31 ^ (n-1) + s [1] * 31 ^ (n-2) +… + s [n-1]

5. Proceso de generación de código interno:

Genere un identificador-> use el código hash de este identificador para ir al hashmap para verificar la existencia-
> si existe, obtenga el código interno de este identificador-
> si no existe, genere un código interno de este identificador Y póngalo en la
representación hashmap de este artículo: var # id

Código:

public class WordAnalyze {
    private static HashMap<String, Integer> keywords = new HashMap<>();
    static {
        //初始化 关键字对应的机内码
        int i = 0;
        keywords.put("int", ++i);
        keywords.put("float", ++i);
        keywords.put("char", ++i);
        keywords.put("if", ++i);
        keywords.put("else", ++i);
        keywords.put("for", ++i);
        keywords.put("while", ++i);
        keywords.put("return", ++i);
        keywords.put("break", ++i);
        keywords.put("continue", ++i);
        keywords.put("switch", ++i);
        keywords.put("case", ++i);
        keywords.put("default", ++i);
        keywords.put("double", ++i);
        keywords.put("void", ++i);
        keywords.put("struct", ++i);
        keywords.put("static", ++i);
        keywords.put("do", ++i);
        keywords.put("short", ++i);
        keywords.put("+", ++i);
        keywords.put("*", ++i);
        keywords.put("/", ++i);
        keywords.put("%", ++i);
        keywords.put("=", ++i);
        keywords.put(">", ++i);
        keywords.put("<", ++i);
        keywords.put("!", ++i);
        keywords.put("==", ++i);
        keywords.put("!=", ++i);
        keywords.put(">=", ++i);
        keywords.put("<=", ++i);
        keywords.put("++", ++i);
        keywords.put("--", ++i);
        keywords.put("&", ++i);
        keywords.put("&&", ++i);
        keywords.put("||", ++i);
        keywords.put("[", ++i);
        keywords.put("]", ++i);
        keywords.put(",", ++i);
        keywords.put(";", ++i);
        keywords.put("(", ++i);
        keywords.put(")", ++i);
        keywords.put("{", ++i);
        keywords.put("}", ++i);
        keywords.put("\"", ++i);
        //单双引号 自己加,java只有单引号
        keywords.put("", ++i);
        keywords.put(":", ++i);
        keywords.put("#", ++i);
        keywords.put(">>", ++i);
        keywords.put("<<", ++i);
        System.out.println("一共" + i + " 个关键字");
        System.out.println("常数类别标识51, 机内码为二进制表示");
        System.out.println("关键字类别标识52, 机内码暂定 ");
        System.out.println("==========================================");
    }

    private FileWriter os;
    private char ch;
    private HashMap<String, String> identifier = new HashMap<>();
    private int identifierCount = 0;

    public WordAnalyze() {

        try {
            File file = new File("目标文件");
            if (file.exists()){
                file.createNewFile();
            }
            os = new FileWriter(file, true);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws Exception {
        File file = new File("源文件");//定义一个file对象,用来初始化FileReader
        FileReader reader = new FileReader(file);//定义一个fileReader对象,用来初始化BufferedReader
        int length = (int) file.length();
        //这里定义字符数组的时候需要多定义一个,因为词法分析器会遇到超前读取一个字符的时候,如果是最后一个
        //字符被读取,如果在读取下一个字符就会出现越界的异常
        char buf[] = new char[length + 1];
        reader.read(buf);
        reader.close();
        new WordAnalyze().analyze(buf);
    }

    //判断是否是关键字
    boolean isKey(String str) {
        if (keywords.containsKey(str))
            return true;
        return false;
    }

    //判断是否是字母
    boolean isLetter(char letter) {
        if ((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z'))
            return true;
        else
            return false;
    }

    //判断是否是数字
    boolean isDigit(char digit) {
        if (digit >= '0' && digit <= '9')
            return true;
        else
            return false;
    }

    //词法分析
    void analyze(char[] chars) {
        String arr = "";
        for (int i = 0; i < chars.length; i++) {
            ch = chars[i];
            arr = "";
            if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
            } else if (isLetter(ch)) {
                while (isLetter(ch) || isDigit(ch)) {
                    arr += ch;
                    ch = chars[++i];
                }
                //回退一个字符
                i--;
                if (isKey(arr)) {
                    //关键字
//                    System.out.println(arr + "  " + keywords.get(arr));
                    writefile(arr + "  " + keywords.get(arr) + "\n");
                } else {
                    //标识符
                    if (identifier.containsKey(arr)) {
                        //如果已经存在这个标识符号了,就get出来
//                        System.out.println(arr + " 52 " + identifier.get(arr));
                        writefile(arr + " 52 " + identifier.get(arr) + "\n");
                    } else {
                        //不存在这个标识符号,就存入并生成一个机内码
                        identifierCount++;
                        identifier.put(arr, "var#" + identifierCount);
//                        System.out.println(arr + " 52 " + identifier.get(arr));
                        writefile(arr + " 52 " + identifier.get(arr) + "\n");
                    }

                }
            } else if (isDigit(ch) || (ch == '.')) {
                while (isDigit(ch) || (ch == '.' && isDigit(chars[++i]))) {
                    if (ch == '.') i--;
                    arr = arr + ch;
                    ch = chars[++i];
                    i--;
                }
                //属于无符号常数
                writefile(arr + " 51 " + Integer.toBinaryString(Integer.parseInt(arr))+"\n");
//                System.out.println(arr + " 51 " + Integer.toBinaryString(Integer.parseInt(arr)));
            } else switch (ch) {
                //运算符
                case '+':{
                    ch = chars[++i];
                    if (ch == '+')
//                        System.out.println("++" + " " + keywords.get("++"));
                        writefile("++" + " " + keywords.get("++") + "\n");
                    else {
//                        System.out.println("=" + " " + keywords.get("+"));
                        writefile("+" + " " + keywords.get("+") + "\n");
                        i--;
                    }
                }
                break;
                case '-': {
                    ch = chars[++i];
                    if (ch == '-')
//                        System.out.println("--" + " " + keywords.get("--"));
                        writefile("--" + " " + keywords.get("--") + "\n");
                    else {
//                        System.out.println("-" + " " + keywords.get("-"));
                        writefile("-" + " " + keywords.get("-") + "\n");
                        i--;
                    }
                }
                break;
                case '=': {
                    ch = chars[++i];
                    if (ch == '=')
//                        System.out.println("==" + " " + keywords.get("=="));
                        writefile("==" + " " + keywords.get("==") + "\n");
                    else {
//                        System.out.println("=" + " " + keywords.get("="));
                        writefile("=" + " " + keywords.get("=") + "\n");
                        i--;
                    }
                }
                break;
                case ':': {
//                    System.out.println(":" + " " + keywords.get(":"));
                    writefile(":" + " " + keywords.get(":") + "\n");
                }
                break;
                case '>': {
                    ch = chars[++i];
                    if (ch == '=')
//                        System.out.println(">=" + " " + keywords.get(">="));
                        writefile(">=" + " " + keywords.get(">=") + "\n");
                    else if (ch == '>')
//                        System.out.println(">>" + " " + keywords.get(">>"));
                        writefile(">>" + " " + keywords.get(">>") + "\n");
                    else {
//                        System.out.println(">" + " " + keywords.get(">"));
                        writefile(">" + " " + keywords.get(">") + "\n");
                        i--;
                    }
                }
                break;
                case '<': {
                    ch = chars[++i];
                    if (ch == '=')
//                        System.out.println("<=" + " " + keywords.get("<="));
                        writefile("<=" + " " + keywords.get("<=") + "\n");
                    else if (ch == '<')
//                        System.out.println("<<" + " " + keywords.get("<<"));
                        writefile("<<" + " " + keywords.get("<<") + "\n");
                    else {
//                        System.out.println("<" + " " + keywords.get("<"));
                        writefile("<" + " " + keywords.get("<") + "\n");
                        i--;
                    }
                }
                break;
                //默认一些
                default:
                    if (keywords.containsKey(String.valueOf(ch))) {
//                        System.out.println(ch + " " + keywords.get(String.valueOf(ch)));
                        writefile(ch + " " + keywords.get(String.valueOf(ch)) + "\n");
                    }
            }
        }
        //在分析结束后,关闭流
        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void writefile(String content) {
        try {
            os.write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Ventajas de implementación del código:

La palabra clave de un solo carácter se puede agregar a voluntad, y la palabra clave de dos caracteres debe modificarse para tener un poco de escalabilidad;
para agregar la palabra clave de doble carácter, debe agregarla en el caso, por supuesto, debe comprender el código

De hecho, puede usar el modo de estrategia del modo de diseño para optimizar lo siguiente. Por supuesto, definitivamente no hay tiempo
. Esto también se puede escribir con una máquina de estados finitos. Esta es la forma más formal de
buscar cómo usar el código para lograr un estado finito. Máquina, este es un tipo de idea en el algoritmo de manipulación de cadenas.

Publicado 37 artículos originales · elogiado 6 · visitas 4642

Supongo que te gusta

Origin blog.csdn.net/littlewhitevg/article/details/105498777
Recomendado
Clasificación