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

  • 格式:docx
  • 大小:311.52 KB
  • 文档页数:18

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

一、 实验目的

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

对某特定语言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、 单词种别定义;

A语言中的单词符号及其对应的种别编码如下表所示:

单词符号 种别编码 单词符号 种别编码 program 1 + 16

begin 2 * 17

end 3 ( 18

var 4 ) 19

int 5 , 20

and 6 . 21

or 7 := 22

not 8 ; 23

if 9 >

24

then 10 < 25

else 11 = 26

while 12 >= 27

do 13 <= 28

标识符 14 <> 29

整型常量 15 - 30

3、 状态转换图;

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

空格符,制表符

或回车符 字母或数字

数字

非字母或数字 2 字母 0 1

非数字 3

+ 数字

5

6

3 1*

7 (

8 ) 4

10 . 9 ,

12 :

1) 1非= =

4、 运行环境介绍;

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

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

程序中用到的函数列表: 25 其他 A类定义各种类函数以及包含主函数public static void main()

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

strToken存放当前字符串

main() //主函数

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

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

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

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

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

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

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

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

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

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

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

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

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

(2)具体分析流程图:

开始

类初始化,变量的初始化,准备执行main()函数

调用Analyse()函数分析

输出结果表

结束

Analyse(str)函数

读取第一个字符赋给变量Ch

继续判读

IndexoutofBound

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

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

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

得到的二元组序列如下:

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

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

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

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

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

四、 实验总结

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

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

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

package Analysis;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import java.util.HashMap;

import java.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 boolean noteTag=false;

private Map< Integer,String > keywords;

private HashMap punctuations;

private static ArrayList p=new ArrayList();

private static ArrayList q=new ArrayList();

// get and set 函数

public char getCh() {

return ch;

}

public void setCh(char ch) {

A.ch = ch;

}

public String getStrToken() {

return strToken;

}

public void setStrToken(String strToken) {

A.strToken = strToken;

}

public void setPunctuations(HashMap punctuations)

{

this.punctuations = punctuations;

}

public Map getPunctuations() {

return punctuations;