Java实现词法分析

Java实现词法分析,第1张

目录

词法分析说明

实现原理分析

代码实现

结果图


词法分析说明

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

例如:

如源程序为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 "+"("+"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 "";
        }
    }


​
结果图

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/737551.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存