Java实现词法分析

目录

词法分析说明

实现原理分析

代码实现

结果图


词法分析说明

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

例如:

如源程序为C语言。输入如下一段:


main()
{
int  a=-5,b=4,j;
if(a>=b) 
j=a-b; 
else  j=b-a;
}

要求输出:

(”main”,1,1)    
(”(”,5)     
(”)”,5)
(”{”,5)       	
(”int”,1,2)     
(”a”,2)
(”=”,4)      
(”-5”,3)      
(”,”,5)
(”b”,2)      
(”=”,4)       
(”4”,3)
(”,”,5)       
(”j”,2)        
(”;”,5)
(”if”,1,3)      
(”(”,5)      
(”a”,2)
(”>=”,4)    
(”b”,2)       
(”)”,5)
(”j”,2)       
(”=”,4)       
(”a”,2)
(”-”,4)       
(”b”,2)       
(”;”,5)
(”else”,1,4) 
(”j”,2)         
(”=”,4)
(”b”,2)      
(”-”,4)        
(”a”,2)
(”;”,5)        
(”}”,5)

实现原理分析

1.  以上述示例代码中,首先明确出现了哪些内容

(1)关键字:例如 int ,if , else

(2)标识符:例如 a , b ,j

(3)常量:例如 5 , 4

(4)运算符:例如 = , -  ,+

(5)界限符:例如 [ ] , { } ,;


2.  基本转换图

 

3.  基本流程图

代码实现

实现的详细过程已在代码中注释

注意!!

代码中有一个内容(关于负数)没有实现,希望有大佬可以改进

​
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;

public class cffx20192697 {
    public static void main(String[] args) {
        cffx20192697.read("D:\\text01.txt");
    }

    /*
    静态初始化一个String类型的数组用于存放C语言中的关键字(t=1),共32个
       auto
       breakcase
       char const continue
       default do double
       else enum extern
       float for
       goto
       if
       int
       long
       register return
       short signed sizeof static struct switch
       typedef
       union unsigned
       void volatile
       while

       由于具有独立意义的单词也需要放在该集合,所以该程序中的以下单词也需要考虑
       main print printf scan scanf
     */
        public static String[] KeyWord = {
            "main","print","printf","scan","scanf","auto","breakcase","char","const","continue",
            "default","do","double","else","enum","extern","float","for","goto","if","int","long",
            "register","return","short","signed","sizeof","static","struct","switch","typedef",
            "union","unsigned","void","volatile","while"
        };
        //定义标识符数组(t=2)
        public static String[] Identifier = new String[1000];



        /*
        同理静态初始化一个String类型的数组,用于存放C语言中的运算符(t=4)
        算术运算符:+ - * / % ++ --
        关系运算符:== != > < >= <=
        逻辑运算符:&& || !
        位运算符:& | ^ ~ << >>
        赋值运算符:= += -= *= /= %= <<= >>= &= ^= !=
        三目运算符:?
         */
        public static String[] Operator = {
                "+", "-", "*", "/","%","++","--",
                "==","!=",">","<",">=","<=",
                "&&","||","!",
                "&","|","^","~","<<",">>",
                "=","+=","-=","*=","/=","%=","<<=",">>=","&=","^=","!=",
                "?"
        };

        /*
        静态初始化一个String类型的数组,用于存放C语言中的边界符(t=5)
        () [] {} , ; "" ''
         */
        public static String[] LineBreaks = {
                "(",  ")", "{", "}" , ";"  , "," , "\"" , "[" , "]" , "'"
        };

        //定义判断信号
        public static int index=0;
        public static int sign=0;


        //传入一个字符串s进行判断
        public static void Judge(String s) {
            //进行遍历
            for(int i = 0 ; i < s.length() ;){
                //调用String类中的的方法charAT():返回指定索引处的字符
                char t = s.charAt(i);
                //排除空格和回车换行后,进入循环
                if( t!=' '&&t!='\t' ){
                    StringBuilder str = new StringBuilder();
                    if (t >= 'a' && t <= 'z') {
                        // 当读取到不是大小写字母或者数字时候判断为一个单词读取完成
                        while (t >= 'a' && t <= 'z' || t >= 'A' && t <= 'Z' || t >= '0' && t <= '9'||t=='_') {
                            //进行字符拼接
                            str.append(t);
                            //读取下一个字符
                            t = s.charAt(++i);
                        }
                        //创建一个信号作为接下来的判断标准
                        int sign=0;
                        //对关键字数组进行遍历
                        for(int j=0;j<KeyWord.length;j++){

                            /*
                            调用equals方法进行判断str拼接后的字符串是否在关键字数组中
                            如果在就输出(1,关键字数组中的位置),信号+1,反之信号不变,说明不是关键字
                              */
                            if(str.toString().equals(KeyWord[j])){
                                //数组下标从0开始,输出需要加1
                                System.out.println(str+" ——> "+"("+"1"+","+(j+1)+")");
                                sign=1;
                            }
                        }

                        //程序进行到这里说明str不是关键字,但是符合关键字的判断条件说明这是一个标识符
                        if(sign==0){
                            //由于数组下标从0开始,所以需要++
                            Identifier[index++]= str.toString();
                            System.out.println(str+" ——> "+"(2)");
                        }

                    /*
                    程序运行到这里说明该字符串不是以字母开头,因为语法规则的原因排除上述情况
                     */

                    //当头字符是在0~9范围内时,说明这是一个常量
                    }else if(t >= '0' && t <= '9'){
                        StringBuilder number = new StringBuilder();
                        while (t >= '0' && t <= '9') {
                            //进行数字拼接
                            number.append(t);
                            t = s.charAt(++i);
                            System.out.println(number+" ——> "+"(3)");
                        }

                    /*
                    当程序进行到此处说明这是以符号开头的,就有可能是
                    (1)界限符
                    (2)运算符
                    (3)负数
                     */
                    }else{
                        //定义两个信号,用于后面判断是否为非法字符
                        int sign1=0;
                        int sign2=0;
                        //两位界限符或运算符
                        if(i+1!=s.length()){
                            //对运算符数组进行遍历
                            for (String value : Operator) {

                                //调用equals方法进行判断,拼接后的字符串是否是运算符数组中的
                                if (value.equals(t + String.valueOf(s.charAt(i + 1)))) {
                                    System.out.println(value + " ——> " + "(4)");
                                    i++;
                                    sign1 = 1;
                                    sign2 = 1;
                                }
                            }
                            //对界限符数组进行遍历
                            for (String lineBreak : LineBreaks) {
                                //调用equals方法进行判断,拼接后的字符串是否是界限符数组中的
                              if (lineBreak.equals(t + String.valueOf(s.charAt(i + 1)))) {
                                    System.out.println(lineBreak + " ——> " + "(5)");
                                    i++;
                                    sign1 = 1;
                                    sign2 = 1;
                                }
                            }
                        }
                        //一位界限符或运算符
                        if(sign1==0){
                            for (String value : Operator) {
                                if (value.equals(String.valueOf(t))) {
                                    System.out.println(value + " ——> " + "(4)");
                                    sign2 = 1;
                                }
                            }
                            for (String lineBreak : LineBreaks) {
                                if (lineBreak.equals(String.valueOf(t))) {
                                    System.out.println(lineBreak + " ——> " + "(5)");
                                    sign2 = 1;
                                }
                            }
                        }

                        //当sign一直为0;就说明这是一个非法字符
                        if(sign2 == 0) {
                            System.out.println(t+"是一个非法字符!请仔细修改!");
                        }
                        //一轮判断结束,开始下一轮判断
                        i++;
                    }
                }

                //空格和换行情况下,直接跳过
                else{
                    i++;
                }
            }
        }

        //定义一个读取文件,以及代码行数的方法
        public static void read(String fileName) {
            File file = new File(fileName);
            BufferedReader reader = null;
            try {
                //换行
                System.out.println();
                System.out.println("结果说明:(m,n){m:单词类型,n:表中位置}  m包含以下五种情况——>1:关键词   2:标识符   3:常数   4:运算符    5:界限符 ");
                reader = new BufferedReader(new FileReader(file));
                String tempString;
                int line = 1;

                //一次读入一行,直到读入null为文件结束
                while ((tempString = reader.readLine()) != null) {
                    //输出行号
                    System.out.println("line " + line + ": " + Result(Result(tempString)));
                    Judge(Result(Result(tempString)));
                    System.out.println();
                    System.out.println();
                    line++;
                }

                //调用close()方法,结束文件的读取
                reader.close();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException ignored) {
                    }
                }
            }
        }

        //定义一个方法用于判断注释符(/* */和//)
        public static String Result(String t) {
            for (int i = 0; i < t.length(); i++) {
                if(t.charAt(i) == '*'&&t.charAt(i+1)=='/'){
                    sign=0;
                    //调用substring方法进行单词的截取
                    return t.substring(i+2);
                }
                if(sign==0){
                    if (t.charAt(i) == '/'&&t.charAt(i+1)=='/') {
                        return t.substring(0, i);
                    }
                    if(t.charAt(i) == '/'&&t.charAt(i+1)=='*'){
                        sign=1;
                        return t.substring(0, i);
                    }
                }
            }
            if(sign ==0){
                return t;
            }
            return "";
        }
    }


​

结果图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Java从跨平台到跨行业

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

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

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

打赏作者

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

抵扣说明:

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

余额充值