编译原理实验报告--词法分析器

更新时间:2023-05-09 15:32:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

编译原理实验—词法分析器

姓名:王吉军

学号:09208015

班级:软件92

一、实验目的

通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。同时增强编写和调试程序的能力。

二、实验内容及要求

对某特定语言A ,构造其词法规则。

该语言的单词符号包括:

保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。

功能要求如下所示:

·按单词符号出现的顺序,返回二元组序列,并输出。

·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。

·如果出现词法错误,报出:错误类型,位置(行,列)。

·处理段注释(/* */),行注释(//)。

·有段注释时仍可以正确指出词法错误位置(行,列)。

三、实验过程

1、词法形式化描述

使用正则文法进行描述,则可以得到如下的正规式:

其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。

A→(ID | NUM | RES | DEL | OPR) *

ID→letter(letter | didit)*

NUM→digit digit*

letter→a| … | z | A | … | Z

digit→ 0 | … | 9

RES→ program | begin | end | var | int | and | or | not | if | then | else | while | do

DEL→( | ) | . | ; | ,

OPR→+ | * | := | > | < | = | >= | <= | <>

如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。空格由空白、制表符和换行符组成。

2、单词种别定义;

3、状态转换图;

语言A的词法分析的状态转换图如下所示:

空格符,制表符

或回车符字母或数字

4、运行环境介绍;

本次实验采用MyEclipse进行代码的编写和编译及运行,编写语言为java 语言;程序的运行环境为windows 7 旗舰版

5、关键算法的流程图及文字解释;

程序中用到的函数列表:

A类定义各种类函数以及包含主函数public static void main()

变量ch储存当前最新读进的字符的地址

strToken存放当前字符串

main() //主函数

Analysis()//分析函数,每次读入一行文件,进行识别处理;

charGetChar(); //取得当前位置的字符的内容放入ch,并提前指向下一个字符;

char GetNextChar();//取得当前位置的下一位置的字符,

StringConCat(); //将ch指向的字符连接到strToken后面

isLetter(); //判断ch指向的字符是否字母

isDigit(); //判断ch指向的字符是否数字

add(p,str); //向p表中插入当前strToken的字符串

BooleanfindKeyWord(str); //检测当前strToken中的字符串是否保留字,若是,则执行getKeyWordKey(str),返回保留字的id,否则,判别其是否是已存在的标示符,若是,返回标示符的id以及该标示符在表中的位置;

findPunctuation()//判断是否是一个保留的符号;

getindex() //返回已经识别的标示符或者是数字的位置下标;

Booleanexist(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回true,否则返回false

void callError(); //出错处理过程,将错误的位置报告出来

(1)main()函数的流程图如下:

(2)具体分析流程图:

6、测试报告(测试用例,测试结果);

首先输入一个不含错误的程序(两种注释)进行检测:

运行后在控制台上得到的结果如下所示:

得到的二元组序列如下:

经检验,输出的是正确的二元组序列。

再输入一个含有错误的程序(含有注释)进行检验:

运行后在控制台上得到的结果如下所示:

经检验,错误的位置是正确的

如果是空文件,编译也会通过;

四、实验总结

通过本次试验,我加深了对编译原理中的词法分析的理解,同时通过动手,更加锻炼了自己。本次试验由于使用的刚刚学习的java语言,通过这次机会加强了自己对java语言的熟悉的使用。

在这次试验中,感谢老师的认真的讲解与同学的无私的帮助。总结来说,自己在这次试验中收获很大。

附:以下为本次实验的源代码:

package Analysis;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileReader;

importjava.io.IOException;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.Map;

public class A {

private static char ch;

private static String strToken;

private static int index = 0;

private static int line = 1;

private static booleannoteTag=false;

private Map keywords;

privateHashMap punctuations; private static ArrayList p=new ArrayList(); private static ArrayList q=new ArrayList();

// get and set 函数

public char getCh() {

returnch;

}

public void setCh(char ch) {

A.ch = ch;

}

public String getStrToken() {

returnstrToken;

}

public void setStrToken(String strToken) {

A.strToken = strToken;

}

public void setPunctuations(HashMap punctuations) { this.punctuations = punctuations;

}

public MapgetPunctuations() {

return punctuations;

}

public void setKeywords(Map keywords) { this.keywords = keywords;

}

public MapgetKeywords() {

return keywords;

}

// 构造函数

public A() {

this.keywords = new HashMap();

keywords.put(1,"Program");

keywords.put(2,"begin");

keywords.put(3,"end");

keywords.put(4,"var");

keywords.put(5,"int");

keywords.put(6,"and");

keywords.put(7,"or");

keywords.put(8,"not");

keywords.put(9,"if");

keywords.put(10,"then");

keywords.put(11,"else");

keywords.put(12,"while");

keywords.put(13,"do");

this.punctuations = new HashMap();

punctuations.put("+", 16);

punctuations.put("*", 17);

punctuations.put("(", 18);

punctuations.put(")", 19);

punctuations.put(",", 20);

punctuations.put(";", 21);

punctuations.put(":=", 22);

punctuations.put(">", 23);

punctuations.put(">=", 24);

punctuations.put("<", 25);

punctuations.put("<=", 26);

punctuations.put(".", 27);

punctuations.put("<>", 28);

punctuations.put("=", 29);

}

// 函数定义(词法分析函数)publicbooleanAnalyse(char[] strArray) {

index = 0;// 每次分析一行完成后就将index置0 char temp1;

introwLength = strArray.length;

outer:while (index

strToken = "";

ch = GetChar(strArray);

if (ch == ';'){

System.out.println("(21,;) ");

}

else if(ch==':')

{

index++;

System.out.println("(22,:=)");

}

else if(ch=='.')

{

System.out.println("(27,.)");

}

else if(ch=='>')

{

if(( temp1=this.getNextChar(strArray))=='=') System.out.println("(24,>=)");

else

{

index--;

System.out.println("(23,>)");

}

}

else if(ch=='<')

{

if(( temp1=this.getNextChar(strArray))=='=') System.out.println("(26,<=)");

else if(temp1=='>')

System.out.println("(28,<>)");

else

{

index--;

System.out.println("(25,<)");

}

}

else if(ch=='*'&¬eTag==false)

{

System.out.println("(17,*)");

}

else if (e92009d1c1c708a1284a4449ng.Character.isLetter(ch)&¬eTag==false) { strToken = contact(strToken, ch);

ch = getNextChar(strArray);

while ((e92009d1c1c708a1284a4449ng.Character.isLetter(ch))

|| (e92009d1c1c708a1284a4449ng.Character.isDigit(ch))) {

strToken = contact(strToken, ch);

ch = getNextChar(strArray);

}

index--;

// System.err.println("!!!"+strToken);

if (findKeyword(strToken)) {

//System.out.println("(15," + strToken.toString() + ")\n");

int i=getKeyWordKey(strToken);

System.out.println("("+i+",--)");

} else

{

if(!exist(p,strToken))

p.add(strToken);

int i=getindex(p,strToken);

//System.out.println("(14," + strToken.toString() + ")\n");

System.out.println("(14,"+i+")");

}

} else if (e92009d1c1c708a1284a4449ng.Character.isDigit(ch)&¬eTag==false) {

strToken = this.contact(strToken, ch);

ch = this.getNextChar(strArray);

while (e92009d1c1c708a1284a4449ng.Character.isDigit(ch)) {

strToken = this.contact(strToken, ch);

ch = this.getNextChar(strArray);

}

index--;

//System.out.println("(15," + strToken.toString() + ")\n");

if(!exist(q,strToken))

q.add(strToken);

int i=getindex(q,strToken);

System.out.println("(15,"+i+")");

strToken = "";

} else if (ch == '/'||noteTag==true) {

intstartj=index; //注释起始位置标记

intstarti=line;

if(noteTag==false){

//System.out.println("该部分是注释注释,从第"+starti+"行第"+startj+"列开始");

}

char temp = this.getNextChar(strArray);

if (temp == '*'&¬eTag==false) {

temp = this.getNextChar(strArray);

while(index

temp = this.getNextChar(strArray);

if(temp=='*'&&( temp1=this.getNextChar(strArray))=='/')

{

index--;

break;

}

if(index>=rowLength)

{

noteTag=true;

break outer;

}

}

}

else if(noteTag==true&&ch!='*')

{

while(index

temp = this.getNextChar(strArray);

if(temp=='*'&&(temp1=this.getNextChar(strArray))=='/')

{

noteTag=false;

//System.out.println(/*"该部分是注释注释,从第"+starti+"行第"+startj+"列开始*/"到第"+line+"行"+"第"+(index-0)+"列为止");

break;

}

}

}

else if(temp=='/')

{

while(true)

{

index++;

if(index>=rowLength)

break outer;

}

}

else

return false;

} else {

String key = String.valueOf(ch);

if (this.findPunctuation(key)) {

System.out.println("("+this.getPunctuation(key)+","

+ key + ")");

} else if (key.equals(" ") || key.equals(" ")) { // ************????????????????????***********

break;

} else

return false;

//System.out.println( "[未知符号] " + key + "\n");

//strToken = "";

}

}

return true;

}

public char GetChar(char[] array) {

try {

while ((array[index]) == ' ') {

index++;

}

index++;// 提前指向下一个字符******************** } catch (ArrayIndexOutOfBoundsException e) { return ' ';

}

return array[index - 1];

}

public char getNextChar(char[] strChar) {

index++;

returnstrChar[index - 1];

}

本文来源:https://www.bwwdw.com/article/rf5e.html

Top