编译原理——词法分析C语言程序JAVA源代码

一、实验目的:

加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。

二、实验内容:

1.要识别的词素:

(1)保留字或关键字:如:BEGIN、 END、VAR、INTEGER、REAL、 IF、 THEN、READ、WRITE、WHILE。

(2)运算符: 如:+、-、*、/、:=、=、>、<、>=、<=

(3)标识符: 用户定义的变量名、常数名、过程名

(4)常数:   如:10、25、100、2.3等整数或实数

(5)界符:   如:‘,’、‘.’ 、‘;’ 、‘(’ 、‘)’、‘{’、‘}’,‘:’

2.词法分析过程所要完成的任务:

(1)给出源程序(要求一段完整的代码)

(2)滤空格

(3)识别保留字

(4)识别标识符

(5)拼数

(6)拼复合词(如:=)

(7)输出源程序的token(词法单元)序列。

需要进行词法分析的源程序:

 识别后的输出序列:

 

 

源代码:

package cifaapp;

import java.io.*;
import java.util.*;


//存放token序列
class token {
    Integer key;
    String value;
    token(Integer key, String value) {
        this.key = key;
        this.value = value;
    }
}
public class app {
	
	
	// 单词种别码, 1-17为关键字种别码
	public static final int CHAR = 1;
	public static final int SHORT = 2;
	public static final int INT = 3;
	public static final int LONG = 4;
	public static final int FLOAT = 5;
	public static final int DOUBLE = 6;
	public static final int FINAL = 7;
	public static final int STATIC = 8;
	public static final int IF = 9;
	public static final int ELSE = 10;
	public static final int WHILE = 11;
	public static final int DO = 12;
	public static final int FOR = 13;
	public static final int BREAK = 14;
	public static final int CONTINUE = 15;
	public static final int VOID = 16;
	public static final int RETURN = 17;
	public static String key[]={"char","short","int","long","float","double","final","static","if","else","while","do","for","break","continue","void","return"}; 
	// 20为标识符种别码
	public static final int ID = 20;

	// 30为常量种别码
	public static final int NUM = 30;

	// 31-40为运算符种别码
	public static final int AS = 31; // =
	public static final int EQ = 32; // ==
	public static final int GT = 33; // >
	public static final int LT = 34; // <
	public static final int GE = 35; // >=
	public static final int LE = 36; // <=
	public static final int ADD = 37; // +
	public static final int SUB = 38; // -
	public static final int MUL = 39; // *
	public static final int DIV = 40; // /

	// 41-49为界限符种别码
	public static final int LP = 41; // (
	public static final int RP = 42; // )
	public static final int LBT = 43; // [
	public static final int RBT = 44; // ]
	public static final int LBS = 45; // {
	public static final int RBS = 46; // }
	public static final int COM = 47; // ,
	public static final int COL = 48; // :
	public static final int SEM = 49; // ;

	// -1为无法识别的字符标志码
	public static final int ERROR = -1;
	public static int errorNum = 0; // 记录词法分析错误的个数

	
	
	public static LinkedList<String> list = new LinkedList<String>();
	public static LinkedList<token> tokenlist = new LinkedList<token>();
	//以行为单位读取文件内容
	public static void readFileByLines() {
		File file = new File("code.txt");
		BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                //System.out.println(tempString);
                separate(tempString);
            }
            reader.close();
        } catch (IOException e) {} 
        
        finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {}
            }
        }
	}
	//正则表达式分离字符串,放入链表中
	public static void separate(String linestring) {
		String temp[]=linestring.split("\\s+|\\n|(?<=\\+)|(?=\\+)|(?<=-)|(?=-)|(?<=\\*)|(?=\\*)|(?<=/)|(?=/)|(?<=\\>)|(?=\\>)|(?<=\\<)|(?=\\<)|(?<==)|(?==)|(?<=\\()|(?=\\()|(?<=\\))|(?=\\))|(?<=\\[)|(?=\\[)|(?<=])|(?=])|(?<=\\{)|(?=\\{)|(?<=})|(?=})|(?<=,)|(?=,)|(?<=:)|(?=:)|(?<=;)|(?=;)");
		for(int i=0;i<temp.length;i++) {
			list.add(temp[i]);
		}
	}
	
	public static void analyse() {
	    for (int i = 0; i < list.size(); i++) {
	        if (list.get(i).length() == 1) {
	            if (list.get(i).equals("=")) { // 运算符"="
	                if (list.get(i+1).equals("=")) { // 若后面跟的是"=",则是运算符"=="
	                	tokenlist.add(new token(EQ, list.get(i) + list.get(++i)));
	                } else { // 否则是运算符"="
	                	tokenlist.add(new token(AS, list.get(i)));
	                }
	            } else if (list.get(i).equals(">")) { // 运算符">"
	                if (list.get(i+1).equals("=")) { // 若后面跟的是"=",则是运算符">="
	                	tokenlist.add(new token(GE, list.get(i) + list.get(++i)));
	                } else { // 否则是运算符">"
	                	tokenlist.add(new token(GT, list.get(i)));
	                }
	            } else if (list.get(i).equals("<")) { // 运算符"<"
	                if (list.get(i+1).equals("=")) { // 若后面跟的是"=",则是运算符"<="
	                    tokenlist.add(new token(LE, list.get(i) + list.get(++i)));
	                } else { // 否则是运算符"<"
	                    tokenlist.add(new token(LT, list.get(i)));
	                }
	            } else if (list.get(i).equals("+")) { // 运算符"+"
	                if ((list.get(i-1).equals("=") || list.get(i-1).equals("("))
	                    && isNum(list.get(i+1))) { // 判断是否是有符号常量(正数)
	                    tokenlist.add(new token(NUM, list.get(i) + list.get(++i)));
	                } else { // 否则是运算符"+"
	                    tokenlist.add(new token(ADD, list.get(i)));
	                }
	            } else if (list.get(i).equals("-")) { // 运算符"-"
	                if ((list.get(i-1).equals("=") || list.get(i-1).equals("("))
	                        && isNum(list.get(i+1))) { // 判断是否是有符号常量(负数)
	                    tokenlist.add(new token(NUM, list.get(i) + list.get(++i)));
	                } else { // 否则是运算符"-"
	                    tokenlist.add(new token(SUB, list.get(i)));
	                }
	            } else if (list.get(i).equals("*")) { // 运算符"*"
	                tokenlist.add(new token(MUL, list.get(i)));
	            } else if (list.get(i).equals("/")) { // 运算符"/"
	                tokenlist.add(new token(DIV, list.get(i)));
	            } else if (list.get(i).equals("(")) { // 界限符"("
	                tokenlist.add(new token(LP, list.get(i)));
	            } else if (list.get(i).equals(")")) { // 界限符")"
	                tokenlist.add(new token(RP, list.get(i)));
	            } else if (list.get(i).equals("[")) { // 界限符"["
	                tokenlist.add(new token(LBT, list.get(i)));
	            } else if (list.get(i).equals("]")) { // 界限符"]"
	                tokenlist.add(new token(RBT, list.get(i)));
	            } else if (list.get(i).equals("{")) { // 界限符"{"
	                tokenlist.add(new token(LBS, list.get(i)));
	            } else if (list.get(i).equals("}")) { // 界限符"}"
	                tokenlist.add(new token(RBS, list.get(i)));
	            } else if (list.get(i).equals(",")) { // 界限符","
	                tokenlist.add(new token(COM, list.get(i)));
	            } else if (list.get(i).equals(":")) { // 界限符":"
	                tokenlist.add(new token(COL, list.get(i)));
	            } else if (list.get(i).equals(";")) { // 界限符";"
	                tokenlist.add(new token(SEM, list.get(i)));
	            } else if (list.get(i).charAt(0) >= '0' && list.get(i).charAt(0) <= '9') { // 判断是否是一位数字常量
	                tokenlist.add(new token(NUM, list.get(i)));
	            } else if (isLetter(list.get(i).charAt(0))) { // 判断是否是一位字母标识符
	                tokenlist.add(new token(ID, list.get(i)));
	            } else { // 否则是无法识别的字符
	                tokenlist.add(new token(ERROR, list.get(i)));
	                errorNum++;
	            }
	        } else if ((list.get(i).charAt(0) >= '0' && list.get(i).charAt(0) <= '9')
	                    || list.get(i).charAt(0) == '.') { // 判断是否是正确的常量
	            if (!isNum(list.get(i))) { // 不是常量,则是无法识别的字符
	                tokenlist.add(new token(ERROR, list.get(i)));
	                errorNum++;
	            } else if ((list.get(i+1).charAt(0) == '+' || list.get(i+1).charAt(0) == '-')
	                    && isNum(list.get(i+2))) { // 判断是否是有符号的常量
	                tokenlist.add(new token(NUM, list.get(i) + list.get(++i) + list.get(++i)));
	            } else { // 否则是无符号的常量
	                tokenlist.add(new token(NUM, list.get(i)));
	            }
	        } else if (isKeyID(list.get(i)) != 0) { // 判断是否为关键字
	            tokenlist.add(new token(isKeyID(list.get(i)), list.get(i)));
	        } else if (isLetter(list.get(i).charAt(0)) || list.get(i).charAt(0) == '_') { // 判断是否为标识符(以字母或者下划线开头)
	            tokenlist.add(new token(ID, list.get(i)));
	        } else { // 否则是无法识别的单词
	            tokenlist.add(new token(ERROR, list.get(i)));
	            errorNum++;
	        	}
	    	}
	    }
	  //判断是否为数字
	    public static boolean isNum(String str){
	       for (int i = str.length();--i>=0;){
	           if (!Character.isDigit(str.charAt(i))){
	               return false;
	           }
	       }
	       return true;
	    }
	    //判断是否为关键字
	    static int isKeyID(String s){
	    	 int i;
	    	 for(i=0;i<6;i++){
	    		 if(s.equals(key[i])) {
	    			 return i;
	    		 }
	    	 }
	    		  return 0;
	    }
	    static boolean isLetter(char c)
	    {
	     if(c>='a' && c<='z')
	      return true;
	     return false;
	    }
	    
	public static void main(String args[]) {
		readFileByLines();
		analyse();
		
		System.out.println(list);
		System.out.println("词法分析结果如下:\n<单词种别码,单词>          //所属类别");
		for(int i=0;i<tokenlist.size();i++){
			System.out.print("<   " + tokenlist.get(i).key + "    " + tokenlist.get(i).value + "  >          ");
			if (tokenlist.get(i).key > 0 && tokenlist.get(i).key < 20) {
		        System.out.println("//关键字");
		    } else if (tokenlist.get(i).key == 20) {
		        System.out.println("//标识符");
		    } else if (tokenlist.get(i).key == 30) {
		        System.out.println("//常量");
		    } else if (tokenlist.get(i).key > 30 && tokenlist.get(i).key <= 40) {
		        System.out.println("//运算符");
		    } else if (tokenlist.get(i).key > 40 && tokenlist.get(i).key < 50) {
		        System.out.println("//界限符");
		    } else if (tokenlist.get(i).key == -1) {
		        System.out.println("//无法识别的符号");
		    }
		}
		System.out.println("词法分析结束!共" + errorNum + "个无法识别的符号");
	}
}

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机科学中的一个重要分支,主要研究如何将高级语言转换为机器语言的过程。其中,词法分析器是编译器中的一个重要组成部分,它负责将源代码中的字符序列转换为有意义的单词序列,也就是词法单元。 下面是一个简单的词法分析器的C语言代码示例: ```c #include <stdio.h> #include <ctype.h> #include <string.h> #define MAX_TOKEN_LEN 100 typedef enum { INT, FLOAT, IDENTIFIER, KEYWORD } TokenType; typedef struct { TokenType type; char value[MAX_TOKEN_LEN]; } Token; char *keywords[] = {"if", "else", "while", "for", "int", "float"}; int is_keyword(char *word) { int i; for (i = 0; i < 6; i++) { if (strcmp(word, keywords[i]) == 0) { return 1; } } return 0; } Token get_token() { Token token; char c = getchar(); while (isspace(c)) { c = getchar(); } if (isdigit(c)) { token.type = INT; int i = 0; while (isdigit(c)) { token.value[i++] = c; c = getchar(); } if (c == '.') { token.type = FLOAT; token.value[i++] = c; c = getchar(); while (isdigit(c)) { token.value[i++] = c; c = getchar(); } } token.value[i] = '\0'; ungetc(c, stdin); } else if (isalpha(c) || c == '_') { token.type = IDENTIFIER; int i = 0; while (isalnum(c) || c == '_') { token.value[i++] = c; c = getchar(); } token.value[i] = '\0'; ungetc(c, stdin); if (is_keyword(token.value)) { token.type = KEYWORD; } } else { token.type = c; } return token; } int main() { Token token; do { token = get_token(); switch (token.type) { case INT: printf("INT: %s\n", token.value); break; case FLOAT: printf("FLOAT: %s\n", token.value); break; case IDENTIFIER: printf("IDENTIFIER: %s\n", token.value); break; case KEYWORD: printf("KEYWORD: %s\n", token.value); break; default: printf("%c\n", token.type); break; } } while (token.type != EOF); return 0; } ``` 这个词法分析器可以识别整数、浮点数、标识符和关键字。它通过一个`get_token()`函数来获取下一个词法单元,并根据单元的类型进行相应的处理。在`get_token()`函数中,它会读取输入流中的字符,根据字符的类型来判断当前单元的类型,并将单元的值存储在一个`Token`结构体中返回。在`main()`函数中,它会不断调用`get_token()`函数来获取下一个单元,并根据单元的类型进行相应的输出,直到读取到输入流的结尾。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值