`
Anddy
  • 浏览: 197939 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

cmm编译器-cmm 语言词法分析-java实现

    博客分类:
  • java
阅读更多

词法设计理念

1.       注释处理: 在处理注释的问题上,我采用了正则表达式处理,在词法分析程序执行前,先讲注释匹配掉,将其换成一个空格。在处理空格上,为了避免对空格多重过滤,依然使用正则表达式将2个或者两个以上的空格匹配成一个空格。这样后在词法分析过程中,逻辑的处理变得更简单。

对注释的处理方法:

public static String omitComment(String str)

2.       词法分析的原理:依然使用的是每次获取一个字符,分析它是字母、数字、操作符、分隔符等以及之前设置状态。这样就可确定碰到这个字符后是什么状态。一共设置了3种状态。

3.       程序的结构说明:

l  程序一开始需要实例一个名为LexicalAnalysis类的对象。这个对象的 构造函数有两个

1. LexicalAnalysis(String sourcefilename)这个构造函数的参数为cmm源码的路径,这样在实例化这个类时就已经将源码加载在实例中。

2. LexicalAnalysis(String sourcefilename, String[] reservedwords)

第二个构造函数较第一个函数多了一个数组的参数,从字面上可以知道,这个参数为关键字的数组,这样以来,用户可以自定义自己关键字。然后构造属于自定义的词法分析程序。同时,如果用户没想自定义关键字就可以使用第一个构造函数并使用了默认的关键字。

 

在实例化词法分析对象时使用了工具类,对要分析的cmm源文件进行读取。读取后将其存在字符串中,便于后面的词法分析。

l  在实例化词法分析对象后,就可以调用分析方法parse() ,

l  在分析过程中,设置一个全局的变量

StringBuilder resultStringBuilder = new StringBuilder();

将其用来保存词法分析的结果。并将其输出。

4.错误的处理:

w  词法分析对数值的错误处理:数值不能以.结尾。

if (charArray[index - 1] == '.') {

                        resultStringBuilder.append(s + ":数值不能以\".\"结尾。\n");

w  词法分析对字符串的处理:标识符不能以下划线结尾。

if (charArray[index - 1] == '_') {

                  resultStringBuilder.append(s + ":标识符不能以\"_\"结尾。\n");

5.测试 

测试数据

int i;

i=1;

/**

*Author:Hyvi

*

*lexical Analysis

*/

if(i==1){

write i;

}else{

i=0;

}

 

输出的结果如下

int:保留字。

t:标识符。

i:标识符。

;:分隔符。

i:标识符。

=:操作符。

1:整数。

;:分隔符。

if:保留字。

(:分隔符。

i:标识符。

==:操作符。

1:整数。

):分隔符。

{:分隔符。

write:保留字。

i:标识符。

;:分隔符。

}:分隔符。

else:保留字。

{:分隔符。

i:标识符。

=:操作符。

0:整数。

;:分隔符。

}:分隔符。

 

======================================

问题列表:

 

问题1

如上cmm源码在第一次运行时出项如下错误:

 

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

    at exercise.LexicalAnalysis.parse(LexicalAnalysis.java:66)

    at exercise.LexicalAnalysis.main(LexicalAnalysis.java:188)

解决方法:

 

根据提示问题错在ch = charArray[index]; 字符串尾部的空格引起的。

修改前:

ch = charArray[index];

 

修改后

while (ch == ' ') {

                  sourcetemp1 = sourcetemp1.substring(1);

                  charArray = sourcetemp1.toCharArray();

                  

                  if(sourcetemp1.length()!=0)ch = charArray[index];

                  else {

                     flag =true ;

                     state =4;

                     break;

                  }

              }

              if(flag){

                  break;

              }

 

这样后在遇到文件结尾时,就跳switch以及while循环。

分析及评价:

词法分析采用有穷机的机制。根据不同的状态及读取的字符决定有穷机的走向。在本次试验中,对于注释的处理是采用了java中正则表达式方法处理,这是一个独到的处理。试验中使用java中对字符串的处理以及数组的操作来完成词法分析。当然一个程序不可能达到完美,总存在着不足的地方。这个词法分析程序也不例外。在对注释的处理里,依然存在这个不足,使用java中的正则表达式的处理的效率可能不及对字符的处理。

 

词法分析主类:

 

package exercise;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import exercise;

public class LexicalAnalysis {
	private String[] reservedwords;
	private String source;
	private String result;
	private static Character[] operators = new Character[] { '+', '-', '*',
			'/', '=', '<', '<', '>' };
	private static Character[] seperators = new Character[] { '(', ')', ';',
			'{', '}', '[', ']' };

	LexicalAnalysis(String sourcefilename) {
		try {
			this.source = BufferedInputFile.read(sourcefilename);
		} catch (IOException e) {
			this.source = "filenotexist";
			// 在console里输出
			System.err.println("读取代码文件失败,可能文件路径出错了");
		}
		this.reservedwords = new String[] { "if", "while", "else", "read",
				"write", "int", "real" };
	}

	public LexicalAnalysis(String sourcefilename, String[] reservedwords) {
		try {
			this.source = BufferedInputFile.read(sourcefilename);
		} catch (IOException e) {
			this.source = "filenotexist";
			// 在console里输出
			System.err.println("读取代码文件失败,可能文件路径出错了");
		}
		this.reservedwords = reservedwords;
	}

	// once parse_begind

	public String parse() {

		if (this.source.equals("filenotexist")) {
			return (this.result = this.source);
		}
		// drop comment and spaces
		String sourcetemp1 = omitComment(this.source);
		// string to charArray
		
		char[] charArray = (sourcetemp1.trim()).toCharArray();
		//System.out.println(sourcetemp1);
		int state = 0;
		int index = 0;
		StringBuilder resultStringBuilder = new StringBuilder();
		
		while (index <= charArray.length) {
			switch (state) {
			// 开始状态
			case 0: {
				index = 0;
				boolean flag =false;
				char ch = charArray[index];
				//System.out.println(ch);
				while (ch == ' ') {
					sourcetemp1 = sourcetemp1.substring(1);
					charArray = sourcetemp1.toCharArray();
					
					if(sourcetemp1.length()!=0)ch = charArray[index];
					else {
						flag =true ;
						state =4;
						break;
					}
				}
				if(flag){
					break;
				}
				if (Character.isLetter(ch) || '_' == ch) {
					state = 1;
				} else if (Character.isDigit(ch)) {
					state = 2;
				} else if (contain(operators, (Character) ch)) {
					state = 3;
				} else if (contain(seperators, (Character) ch)) {
					String s = charArrayToString(charArray, index+1);
					resultStringBuilder.append(s + ":分隔符。\n");
					sourcetemp1 = sourcetemp1.substring(index + 1);
					charArray = sourcetemp1.toCharArray();
					state = 0;
				} else {
					resultStringBuilder.append("error");
					sourcetemp1 = sourcetemp1.substring(index + 1);
					charArray = sourcetemp1.toCharArray();
					state = 0;

				}
				break;
			}
			case 1: {
				char ch = charArray[index];
				if (Character.isLetter(ch) || '_' == ch
						|| Character.isDigit(ch)) {
				} else {
					String s = charArrayToString(charArray, index);
					if (contain(reservedwords, s)) {
						resultStringBuilder.append(s + ":保留字。\n");

					} else if (charArray[index - 1] == '_') {
						resultStringBuilder.append(s + ":标识符不能以\"_\"结尾。\n");
					} else {
						resultStringBuilder.append(s + ":标识符。\n");
					}
					sourcetemp1 = sourcetemp1.substring(index);
					charArray = sourcetemp1.toCharArray();
					state = 0;
				}
				break;
			}
			case 2: {
				char ch = charArray[index];
				if (Character.isDigit(ch))
					state = 2;
				else if (ch == '.')
					state = 2;
				else {
					String s = charArrayToString(charArray, index);
					if (charArray[index - 1] == '.') {
						resultStringBuilder.append(s + ":数值不能以\".\"结尾。\n");
					}else if(s.contains(".")){
						resultStringBuilder.append(s + ":实数。\n");
					} 
					
					else {
						
						resultStringBuilder.append(s + ":整数。\n");
					}
					sourcetemp1 = sourcetemp1.substring(index);
					charArray = sourcetemp1.toCharArray();
					state = 0;
				}
				break;
			}
			case 3: {
				char ch = charArray[index];
				if (ch == '>' || ch == '=') {
					state = 3;
				} else {
					String s = charArrayToString(charArray, index);
					resultStringBuilder.append(s + ":操作符。\n");
					sourcetemp1 = sourcetemp1.substring(index);
					charArray = sourcetemp1.toCharArray();
					state = 0;
				}
				break;
			}
			default: {
				resultStringBuilder.append("");
				break;
			}
			}
			index++;
		}
		if (resultStringBuilder.toString().contains("error"))
			resultStringBuilder = new StringBuilder("error");
		return this.result = resultStringBuilder.toString();
	}

	public static String charArrayToString(char[] array, int index) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < index; i++) {
			sb.append(array[i]);
		}
		return sb.toString();
	}

	public static String omitComment(String str) {
		String result = "";
		Pattern pattern = Pattern
				.compile("(/\\u002A(.*?)(\n(.*?))*\\u002A/|//.*\\n)");
		Matcher matcher = pattern.matcher(str);
		String temp = matcher.replaceAll(" ");
		result = (pattern.compile("(\\n|\\t|\\r| |\f)+")).matcher(temp)
				.replaceAll(" ");
		return result;
	}

	public static <T> boolean contain(T[] array, T t) {
		boolean flag = false;
		for (T a : array) {
			if (a.equals(t))
				flag = true;
		}
		return flag;
	}

	public static void main(String[] args) {
		LexicalAnalysis s = new LexicalAnalysis("C:/1.txt");
		System.out.println(s.parse());
	}

	public String[] getReservedwords() {
		return reservedwords;
	}

	public String getSource() {
		return source;
	}

	public String getResult() {
		return result;
	}

	public void setReservedwords(String[] reservedwords) {
		this.reservedwords = reservedwords;
	}

	public void setSource(String source) {
		this.source = source;
	}

	public void setResult(String result) {
		this.result = result;
	}

}

 工具类:

 

package exercise;

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


public class BufferedInputFile {
	public static String read(String filename) throws IOException{
		BufferedReader bufferedReader =new BufferedReader(new FileReader(filename));
		StringBuilder builder =new StringBuilder();
		String str;
		while((str=bufferedReader.readLine())!=null){
			builder.append(str+"\n");
		}
		bufferedReader.close();
		return builder.toString();
	}
	
}

 

 

 

分享到:
评论

相关推荐

    java做的CMM语言词法分析器

    本项目聚焦于词法分析阶段,使用Java语言实现了一个针对CMM(假设是一种自定义的编程语言)的词法分析器。 词法分析,也称为扫描或标记,是编译器或解释器的第一个阶段。它的任务是将源代码分解成一系列的有意义的...

    CMM词法分析器 使用java语言实现

    本文将深入探讨如何使用Java语言来实现一个CMM词法分析器。 词法分析器,也称为扫描器或词法器,其主要任务是将源代码文本转换为一系列有意义的标记(tokens),这些标记是语言的基本构建块,如关键字、标识符、...

    cmm词法分析(java)

    下面我们将深入探讨CMM词法分析的原理、Java实现的关键技术和相关知识点。 1. **词法分析定义与作用** 词法分析,又称扫描或词法生成,是编译器前端的第一步。它的主要任务是识别源代码中的关键字、标识符、常量、...

    CMM.rar_CMM_cmm词法分析器_编译 词法分析 java

    "CMM_cmm词法分析器"指的是该压缩包内包含CMM语言的词法分析器源码,这可能是用Java编程语言实现的。Java是一种广泛使用的面向对象的编程语言,具有跨平台的特性,因此适合开发这样的工具。 描述中提到的"CMM语言...

    cmm.rar_CMM_CMM java_CMM词法_cmm语法_语法 树

    本压缩包"**cmm.rar**"包含了关于CMM编译器的详细资料,特别是针对Java语言的实现。以下是基于提供的文件信息解析出的相关知识点: 1. **CMM Java**: CMM可以应用于Java语言,创建一个用于处理Java源代码的编译器。...

    CMM.rar_CMM解释器_CMM词法_CMM语言_CMM语言解释器_cmm词法分析

    而"**CMM词法分析器**"可能是一个实现了这个功能的Java程序,这表明开发者选择Java作为实现词法分析器的编程语言,Java以其跨平台性和丰富的库支持而受到青睐。 词法分析是编译器构造的重要组成部分,它对程序的...

    Cmm.rar_CMM_JAVA CMM_cmm语法_词法语法_语法 词法

    "**cmm语法 词法语法 语法_词法**"这些标签进一步强调了Cmm编译器对语言规范的重视,特别是关于如何定义和解析语言的结构。 最后,压缩包内的"Cmm"文件可能是编译器的源代码,包含了实现上述功能的函数和数据结构。...

    CMM 编译器

    CMM编译器包含的主要部分有前端分析、中间代码生成、优化以及后端代码生成等关键组件。 1. **前端分析**:这一阶段主要包括词法分析、语法分析和语义分析。词法分析将源代码分解成一个个有意义的符号(token),...

    CMM词法分析器

    CMM词法分析器是基于Java编程语言实现的一个解析工具,主要用于处理CMM(可能是某种特定的编程语言或标记语言)的源代码。词法分析是编译器设计中的一个关键阶段,它将源代码分解成一系列有意义的、独立的单元,称为...

    cmm词法分析器作业

    在这个特定的案例中,"cmm词法分析器作业"是一个关于构建词法分析器的项目,使用了ANTLR工具,并以Java语言作为开发语言。ANTLR是一个强大的解析器生成器,广泛应用于语法解析任务,如编程语言、配置文件等的解析。 ...

    CMM词法分析器 c#

    本篇将深入探讨CMM词法分析器以及如何使用C#来实现这一功能。 首先,词法分析(也称为扫描或Tokenization)是编译器或解释器的第一个阶段。它的任务是将源代码分解成一系列有意义的、独立的元素,称为词法单元或...

    CMM 语言 编译原理 词法分析器

    在CMM语言的编译器中,这个词法分析器可能就是用lex或flex编写,或者完全用C语言手工实现的。 在构建词法分析器时,开发者需要定义每个标记的模式,并指定当遇到这些模式时应如何处理。一旦词法分析器完成,它将为...

    基于ANTLR4的CMM语言编译器

    总结来说,"基于ANTLR4的CMM语言编译器"项目展示了如何使用ANTLR4工具来设计和实现一个编译器,包括文法定义、词法分析、语法分析、语义分析和代码生成等关键步骤。对于学习编译原理和实践编译器开发的人员来说,这...

    java写的--CMM语言解释器

    总的来说,通过实现CMM解释器,我们可以深入了解编译器和解释器的工作流程,掌握词法分析、语法分析和语义分析的关键技术,同时提升Java编程能力。这是一个极好的实践项目,适合对编译原理感兴趣的初学者和开发者...

    基于Java实现的CMM语言解释器,包括词法分析,语法分析等.zip

    【标题】: "基于Java实现的CMM语言解释器,包括词法分析,语法分析等" 这个项目涉及到了计算机编程中的一个重要领域——编译原理,具体是关于如何使用Java语言来构建一个CMM语言的解释器。CMM可能是一种自定义的...

    CMM-parser.rar_CMM_CMM语法分析_cmm parser_cmm词法分析器

    **CMM词法分析器**:词法分析器,又称扫描器,是编译器的第一步。它将源代码分解成一个个独立的、有意义的符号,称为“词法单元”或“token”。这些词法单元可能是关键字、标识符、常量、运算符等。词法分析器通过...

    cmm语言词法分析

    在“解释器作业2”这个文件中,很可能是对CMM语言词法分析的实现或测试案例。可能包含了各种源代码片段,以及预期的标记序列。通过运行词法分析器,可以检查它是否能正确地将源代码转换为标记流。这通常涉及到正则...

    CMM编译器 词法分析 语法分析 解释执行 C#编写

    这是我们大三的时候的一个编译器实践的课程设计,是将CMM语言(自行定义的一个C语言的子集)源程序进行词法分析、语法分析和最终编译运行,包括有源代码和相关文档,希望对初步学习编译器的同学有用,但不提倡直接拿...

    CMM_词法分析和语法分析_java编写

    本文将深入探讨“CMM_词法分析和语法分析_java编写”这一主题,结合Java语言来实现对CMM语言的解析。 首先,我们需要理解词法分析和语法分析的基本概念。词法分析,也称为扫描或分词,是编译器或解释器的第一个阶段...

Global site tag (gtag.js) - Google Analytics