实验1《词法分析程序设计与实现》(java版)

目录

第1关:词法分析程序设计与实现

任务描述

相关知识

词法分析的基本知识

实验步骤

编程要求

测试说明

答案:


第1关:词法分析程序设计与实现

任务描述

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

相关知识

为了完成本关任务,你需要掌握:词法分析程序设计与实现。

词法分析的基本知识

词法分析程序( Lexical analyzer,简称 Lexer ),负责从左到右逐个字符地对源程序进行扫描和分解,根据语言的词法规则识别出一个个的单词符号。

因此一个词法分析程序应具备如下功能:

从左至右扫描构成源程序的字符流

识别出有词法意义的单词

返回单词记录,或词法错误信息

由上可知词法分析中的一个重要环节为识别单词符号类型,为了便于语法分析,通常将单词符号分为五类。

        标识符 用来命名程序中出现的变量、数组、函数、过程、标号等,通常是一个字母开头的字母数字串,如 length,nextch 等。

        基本字 也可以成为关键字或保留字。如 if,while,for,do,goto 等。他们具有标识符的形式,但他们不是由用户而是由语言定义的,其意义是约定的。多数语言中规定,他们不能作为标识符或者标识符的前缀,即用户不能使用它们来定义用户使用的名字,故我们称它为保留字,这些语言如 Pascal 和 C 等。但也有的语言允许将基本字作为标识符或者标识符的前缀,这类语言如 Fortran 等。

        常数 包括各种类型的常数,如整型、实型、字符型、布尔型等。如:53.1415926aTRUE等都是常数。

        运算符 算术运算符+-×÷;关系运算符<,<=,>,>=,==,!=以及逻辑运算符&&()||或者!等。

        界符 如等单字界符和/,/,//等双字界符,空白符等。

在进行词法分析后,识别出来的单词应该采用某种中间表示形式,以便为编译后续阶段方便地引用。通常一个单词用一个二元式来表示: (单词类别,单词的属性) 其中,第一元用于区分单词所属的类别,以整数编码表示。第二元用于区分该类别中的哪一个单词符号,即单词符号的值。

实验步骤

由一个词法分析程序应具备的功能来看,我们的程序具有如下要求:

对单词的构词规则有明确的定义;

编写的分析程序能够正确识别源程序中的单词符号;

识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;

对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;

下面我们进行实验代码的步骤分析。

定义目标语言的可用符号表和构词规则。
我们需要对五种单词符号进行识别分析,这里将单词符号分为三大块进行识别。首先判断字符是否为关键字或者标识符,并与已定义好的关键字进行比较,从而判断为关键字或者标识符;然后是数字的识别;最后是其他字符的判断,它们被一一定义好的判断进行识别,这样所有的字符便被识别出来了。标示符和关键

字的判断

  String token= String.valueOf(str.charAt(p++));
     char ch;
     for (;p<str.length();p++){
         ch=str.charAt(p);
         if (!Character.isLetterOrDigit(ch)&&ch!='_'){
             break;
         }else{
             token+=ch;
         }
     }  //可能是标示符或者关键字 

字符与关键字的区别通过对比得出:

 if (keyWords.contains(token)){
         System.out.println("("+1+","+token+")");
     }else {
         System.out.println("("+2+","+token+")");
     }

对于数字的识别:

  String token= String.valueOf(str.charAt(p++));
     int flag=0;
     boolean err=false;
     char ch;
     for (;p<str.length();p++) {
         ch = str.charAt(p);
         if (ch==' '||(!Character.isLetterOrDigit(ch)&&ch!='.')) {
             break;
         }else if (err){
             token+=ch;
         }
         else {
             token+=ch;
             if (ch == '.') {
                 if (flag == 1) {
                     err = true;
                 } else {
                     flag++;
                 }
             }else if (Character.isLetter(ch)){
                 err=true;
             }
         }
     } 

其他字符的识别,可以根据初始化中,对他们的定义一一比对进行识别。

依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束。
字符的输入我们使用读取文件逐行进行获取:

 init();
     File file=new File("/data/workspace/myshixun/input.txt");
     lines=1;
     try(Scanner input=new Scanner(file)) {
         while (input.hasNextLine()){
             String str=input.nextLine();
             analyze(str);
             lines++;
         }
     } 

对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;

对不正确的单词,做出错误处理。 单词识别后,我们对返回的符号按3,4的规则进行输出,此处以识别常数为例:

    if (err){
         System.out.println(lines+"line"+": "+token+" is wrong");
     }else {
         System.out.println("("+3+","+token+")");

编程要求

根据提示,在右侧编辑器Beign和End 之间依次补充标示符关键字 letterCheck、数字符digitCheck及其他字符符号symbolCheck的识别程序,点击评测,运行程序,系统会自动进行结果对比。

测试说明

平台会对你编写的代码进行测试:

测试输入:

public class Hello{
    public static void main(String args[]){
        System.out.println("Hello World");
    }
}
 
答案:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

public class ex1 {
	/*
	 * 1表示关键字
	 * 2表示标识符
	 * 3表示常数
	 * 4表示运算符
	 * 5表示界符
	 * 6表示字符串
	 * */
	
	//关键字
	static String []keyWord={"private","protected","public","abstract","class","extends","final","implements",
		"interface","native","new","static","strictfp","break","continue","return","do","while","if","else","for",
		"instanceof","switch","case","default","boolean","byte","char","double","float","int","long","short",
		"String","null","true","false","void","this","goto"};
	//运算符
	static String []operation={"+","-","*","/","%","++","--","-=","*=","/=","&","|","^","~","<<",">>",">>>","==","!=",
		">","<","=",">=","<=","&&","||","!","."};
	//界符
	static String []symbol={",",";",":","(",")","{","}"};
	static ArrayList<String> keyWords=null;
	static ArrayList<String> operations=null;
	static ArrayList<String> symbols=null;
	
	//指向当前所读到字符串的位置的指针
	static int p,lines;
	
	
	public static void main(String []args) throws FileNotFoundException {
		init();
		File file=new File("/data/workspace/myshixun/input.txt");
		lines=1;
		try(Scanner input=new Scanner(file)) {
			while (input.hasNextLine()){
				String str=input.nextLine();
				analyze(str);
				lines++;
			}
		}
		
	}
	
	//初始化把数组转换为ArrayList
	public static void init(){
		keyWords=new ArrayList<>();
		operations=new ArrayList<>();
		symbols=new ArrayList<>();
		Collections.addAll(keyWords, keyWord);
		Collections.addAll(operations, operation);
		Collections.addAll(symbols, symbol);
	}
	
	public static void analyze(String str){
		char ch;
		str=str.trim();
		for (p=0;p<str.length();p++){
			ch=str.charAt(p);
			if (Character.isDigit(ch)){
				digitCheck(str);
			}else if (Character.isLetter(ch)||ch=='_'){
				letterCheck(str);
			}else if (ch=='"'){
				stringCheck(str);
			}
			else if (ch==' '){
				continue;
			}else {
				symbolCheck(str);
			}
		}
	}
	/********Beign********/
	/*数字的识别*/
	public static void digitCheck(String str){
		String token=String.valueOf(str.charAt(p++));
		int f=0;
		boolean st=false;
		char ch;
		for (;p<str.length();p++){
			ch=str.charAt(p);
			if(ch==' '||(!Character.isLetterOrDigit(ch)&&ch!= '.')){
				break;
			}else if(st){
				token+=ch;
			}else{
				token+=ch;
				if(ch=='.'){
					if(f==1){
						st=true;
					}else{
						f++;
					}
				}else if(Character.isLetter(ch)){
					st=true;
				}
			}
		}
		if(st){
			System.out.println(lines + "line: " + token + "is wrong");
		}else{
			System.out.println("(3," + token + ")");
		}
		
		p--;
	}
	/********End********/
	
	/********Beign********/
	//标识符,关键字的识别
	public static void letterCheck(String str){
		String token=String.valueOf(str.charAt(p++));
		char ch;
		for (;p<str.length();p++){
			ch=str.charAt(p);
			if(!Character.isLetterOrDigit(ch)&&ch!='_'){
				break;
			}else{
				token+=ch;
			}
		}
		
		if(keyWords.contains(token)){
			System.out.println("(1," + token +")");
		}else{
			System.out.println("(2," + token +")");
		}
		
		p--;
	}
	/********End********/
	
	/********Beign********/
	//符号的识别
	public static void symbolCheck(String str){
		String token="";
		char ch;
		for (;p<str.length();p++){
			ch = str.charAt(p);
			
			if(Character.isLetterOrDigit(ch)||ch==' '){
				break;
			}else{
				token+=ch;
			}
			
			if(symbols.contains(token)){
				System.out.println("(5," + token +")");
				return;
			}else if(operations.contains(token)){
				System.out.println("(4," + token +")");
				return;
			}
			
		}
		
		p = p - token.length();
		System.out.println(lines+"line"+": "+token.charAt(0)+" is wrong");
		
	}
	/********End********/
	
	//字符串检查
	public static void stringCheck(String str){
		String token= String.valueOf(str.charAt(p++));
		char ch;
		for (;p<str.length();p++){
			ch=str.charAt(p);
			token+=ch;
			if (ch=='"'){
				break;
			}
		}
		if (token.charAt(token.length()-1)!='"'){
			System.out.println(lines+"line"+": "+token+" is wrong");
		}else {
			System.out.println("("+6+","+token+")");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星与星熙.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值