实验一 根据状态转换图手工构造词法扫描器

 

一、实验目的

1. 理解词法分析器的基本功能

2. 理解词法规则的描述方法

3. 理解状态转换图及其实现

4. 能够编写简单的词法分析器

 

二、实验平台

任选

 

三、实验内容

编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符五大类。并依次输出各个单词的内部编码及单词符号自身值。

单词的内部编码如下:

1、保留字:if、int、for、while、do、return、break、continue;单词种别码为1;

2、标识符:除保留字外的以字母开头,后跟字母、数字的字符序列;单词种别码为2;

3、常数为无符号整形数;单词种别码为3;

4、运算符包括:+、-、*、/、=;单词种别码为4;

5、分隔符包括:,、;、{、}、(、); 单词种别码为5。

 

1.画出识别所有单词的状态转换图。(若状态转换图过于复杂,可以只画出主要部分)

 

 

 

2. 根据状态转换图手工构造词法扫描器。从以下方法中选一:

² 词法分析器可以作为独立的一遍

² 也可以作为一个子程序被语法分析器调用

 

 

 

3. 实现状态转换图。

 

/**

 * @author ywq

 * @date 2020/10/14 11:00

 */

 

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.Reader;

import java.util.Arrays;

import java.util.List;

import java.util.Scanner;

 

 

 

public class Test {

 

    static Scanner sc = new Scanner(System.in);

 

    // 保存关键字

    private static List<String> KeyWords;

    // 保存操作符

    private static List<String> Operators;

    // 保存界符

    private static List<String> Boundarys;

 

    private static List<String> Spaces;

    static String str="";

    public static String  readFileByChars(String fileName) {

        File file = new File("E:\\JAVACODE\\rjgz\\rjgz01\\src\\t.txt");

        Reader reader = null;

 

 

        try {

            //System.out.println("以字符为单位读取文件内容,一次读多个字符:");

            // 一次读多个字符

            char[] tempchars = new char[300];

            int charread = 0;

            reader = new InputStreamReader(new FileInputStream("E:\\JAVACODE\\rjgz\\rjgz01\\src\\t.txt"));

            // 读入多个字符到字符数组中,charread为一次读取字符数

 

            while ((charread = reader.read(tempchars)) != -1) {

                // 同样屏蔽掉r不显示

                if ((charread == tempchars.length)

                        && (tempchars[tempchars.length - 1] != '~')) {

                    System.out.print(tempchars+"1");

                } else {

                    for (int i = 0; i < charread; i++) {

                        if (tempchars[i] == '~') {

                            continue;

                        } else {

                            str+=tempchars[i];

                            //System.out.print(tempchars[i]);

 

                        }

                    }

                    //System.out.println("str="+str);

                }

            }

        } catch (Exception e1) {

            e1.printStackTrace();

        } finally {

            if (reader != null) {

                try {

                    reader.close();

                } catch (IOException e1) {

                }

            }

        }

        return str;

    }

    // 初始化

    static {

        // 关键字数组 --> 关键字列表

        String[] keywordArr = { "public", "private", "protected", "short",

                "int", "long", "char", "float", "double", "boolean", "static",

                "void", "for","while" ,"return","continue"};

        KeyWords = Arrays.asList(keywordArr);

 

        // 操作符数组 --> 操作符列表

        String[] operatorArr = { "+", "-", "*", "/", "%", "=", ">", "<", "&" };

        Operators = Arrays.asList(operatorArr);

 

        // 界符数组 --> 界符列表

        String[] boundaryArr = { "" + '{', "" + '}', "" + '[', "" + ']',

                "" + '(', "" + ')', "" + ';' , "" + '.' };

        Boundarys = Arrays.asList(boundaryArr);

 

        // 空格字符数组 --> 空格字符列表

        String[] SpaceArr = { " ", "\t", "\n" };

        Spaces = Arrays.asList(SpaceArr);

    }

    static boolean isDelimiter = false;//是否有分隔符

 

    // 字符串缓冲

    static StringBuffer strb = new StringBuffer();

 

    public static void main(String[] args) {

        String inStr =  readFileByChars("text.txt");

        //System.out.println("+++"+inStr);

        System.out.println("####################简单词法分析器#####################");

        for (char ch : inStr.toCharArray()) {

            match(ch);

        }

 

 

    }

 

    static void match(char ch) {

        // 分割符缓冲

        StringBuffer bouStrb = new StringBuffer();

        // 1. 判断字符类型

        /**

         * (空格|操作符|界符)都是(关键字|标识符|数字)的分割符

         * 即,任意两个(关键字|标识符|数字)之间不可直接相连,而无分割符(空格|操作符|界符)

         */

        // 1.0 空格,返回空格

        if (Spaces.indexOf(ch + "") >= 0) {

            isDelimiter = true;

 

        }

        // 1.1. 操作符, 返回"operator"

        if (Operators.indexOf(ch + "") >= 0) {

            isDelimiter = true;

            bouStrb = new StringBuffer(ch + " 是操作符  单词种别码为4");

        }

        // 1.2 界符, 返回"boundary"

        if (Boundarys.indexOf(ch + "") >= 0) {

            isDelimiter = true;

            bouStrb = new StringBuffer(ch + " 是界符 单词种别码为5");

        }

        // 2. 如果是分割符,

        /**

         * 判断strb中有缓冲字符串, 2.1 若有,检查其是不是常数(暂不接受负数) 2.1.1 若是, 输出字符串,

         * 并标识该字符串为constant 2.1.2 若不是, 检查在不在关键字表中, 2.1.2.1 若在,

         * 输出字符串,并标识该字符串为keyword 2.1.2.2 若不在, 输出字符串,并标识该字符串为identifier

         *

         * 还原变量初始设置,并退出

         */

        if (isDelimiter) {

            if (strb.length() > 0) {

                if (strb.charAt(0) >= '0' && strb.charAt(0) <= '9') {

                    System.out.println(strb + " 是常数 单词种别码为3");

 

                } else if (KeyWords.indexOf(strb.toString()) >= 0) {

                    System.out.println(strb + " 是关键字  单词种别码为1");

                } else {

                    System.out.println(strb + "是标识符  单词种别码为2");

                }

            }

            if (bouStrb.length() > 0)

                System.out.println(bouStrb);

            strb.setLength(0);

            isDelimiter = false;

            return;

        }

 

 

        // 3. 进行到该步,说明字符不是分割符,则把该字符追加到strb中即可

        strb.append(ch);

 

    }

}

结果截图

 

 

 

 

 

 

 

posted @ 2020-11-25 15:54  祈欢  阅读(701)  评论(0编辑  收藏  举报