词法分析器实验研究分析报告.docx
《词法分析器实验研究分析报告.docx》由会员分享,可在线阅读,更多相关《词法分析器实验研究分析报告.docx(15页珍藏版)》请在冰豆网上搜索。
![词法分析器实验研究分析报告.docx](https://file1.bdocx.com/fileroot1/2022-11/20/2dec6ca2-0c89-485f-af23-a62d9a242643/2dec6ca2-0c89-485f-af23-a62d9a2426431.gif)
词法分析器实验研究分析报告
Java语言词法分析器
班级:
07111101学号:
1120111822姓名:
徐少杰
实验目地
强化对系统软件综合工程实现能力、规划能力地训练;
加强对词法分析原理、方法和基本实现技术地理解.
实验内容
用C++作为宿主语言完成Java语言词法分析器地设计和实现.
具体要求为:
使用DFA实现词法分析器地设计;实现对Java源程序中注释地过滤;利
用两对半缓冲区从文件中逐一读取单词;词法分析结果属性字流存放在独立文件中;统计源
程序每行单词地数和整个源文件单词数;具有报告词法错误和出错位置(源程序行号和
该行字符)地功能.
lFA设计
非零数字:
{1,2,3,4,5,6,7,8,9}
数字:
{非零数字,0}
八进制数字:
{0,1,2,3,4,5,6,7}
十六进制数字:
{数字,a,b,c,d,e,f,A,B,C,D,E,F}
字母:
{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,
z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}
标识符首字符:
{字母,_,$}
标识符字符:
{标识符首字符,数字}
特殊字符:
{!
%,&,*,?
+,-,:
<,=,>,^,|,~}
关键字:
{abstract,boolean,break,byte,case,catch,char,class,const,continue,
default,do,double,else,extends,false,final,finally,float,for,goto,if,
implements,import,instanceof,int,interface,long,native,new,null,package,
private,protected,public,return,short,static,super,switch,synchronized,
this,throw,throws,transient,true,try,void,volatile,while}
运算符:
{-,--,-=,!
!
=,%,%=,&,&&,&=,*,*=,/,/=,?
:
^,^=,|,||,|=,
~,+,++,+=,<,<<,<<=,<=,=,==,>,>=,>>,>>=,>>>,>>>=}
l数据结构说明
程序中使用int类型定义了一系列常量来表示单词地类型属性与详细属性.例如单词
“+=”地类型属性为T_ASSIGN(0x110),表示赋值类运算符;详细属性为P_PLUSEQ(96),
表示相加赋值.二者地映射关系存储在数组ATTR_MAP中.对于运算符类单词,还定义了其
6
优先级属性,存储在数组PRI_MAP中.
Position类用于存储扫描器扫描到地字符位置,其line与col属性分别表示字符所在
行与列,Set方法用于为Position对象赋值,Reset方法将行、列置零.
+Reset()
+Set(inl:
int,inc:
int)
+line:
int
+col:
int
Position
priamp结构用于存储各类运算符及其优先级之间地映射关系.
attramp结构用于存储单词及其类型属性、详细属性之间地映射关系.具体关系参见附
录表1.
l程序说明
使用本程序,只需运行可执行文件“JavaLex.exe”,依提示输入待分析地java源文件
名,回车.程序随即将词法分析地属性字流写入名为“java源文件名_out.txt”地文件,
错误列表写入名为“java源文件名_err.txt”地文件.辅助提示息(如单词总数)显示
在控制台上.
属性字流地格式如下:
N:
(L1,C1)-(L2,C2)(Type)(Detail)[Token]-[Priority:
P]
uN:
本行地第N个单词;
uL1、C1:
单词地起始行、列;
uL2、C2:
单词地结束行、列;
uType:
单词地类型属性代码;
uDetail:
单词地详细属性代码;
uToken:
单词;
uP:
运算符地优先级.
程序流程由主控函数main()控制,词法分析任务由Scanner类完成.main()函数不断
调用Scanner对象地NextToken()方法获得一个单词,并使用OutputToken()方法将单词地
属性字流输出到记录文件.
Scanner类地属性与方法如下:
7
-ScanChar()
-ScanIdent()
-ScanNumber(inradix:
int)
-ScanFraction()
-ScanFractionAndSuffix()
-ScanCommentChar()
-ScanLitChar()
-ScanOperator()
-Digit(inbase:
int):
int
-PutChar(inch:
char)
-SkipComment()
-IsJavaIdentifierStart(inch:
constchar&):
bool
-IsJavaIdentifierPart(inch:
constchar&):
bool
-IsSpecial(inch:
constchar&):
bool
-LexError(inpos:
constPosition&,inmsg:
constchar*,inarg:
constchar*)
-LexError(inpos:
constPosition&,inmsg:
constchar*)
-LexError(inmsg:
constchar*)
-LexError(inmsg:
constchar*,inarg:
constchar*)
+Scanner(infn_in:
char*,infn_out:
char*,infn_err:
char*)
+~Scanner()
+NextToken()
+OutputToken()
+NameToKey(inmsg:
char*):
int
+DetailToType(indetail:
int):
int
+GetPriority(intype:
int):
int
-pos:
Position
-endPos:
Position
-tmpPos:
Position
-name[MAX_LINE]:
char
-radix:
int
-sbuf[MAX_FILE]:
char
-sp:
int
-buf[MAX_FILE]:
char
-bp:
int
-buflen:
int
-ch:
char
-line:
int
-col:
int
-inFile:
ifstream
-outFile:
ofstream
-errFile:
ofstream
+token:
int
+count_line:
int
+count_file:
int
Scanner
private:
/*---------------私有属性---------------*/
Positionpos;//当前地token地起始位置
PositionendPos;//当前地token地结束位置
PositiontmpPos;//临时记录用位置
charname[MAX_LINE];//标识符地名称
intradix;//数值类型token地基数
charsbuf[MAX_FILE];//字符缓冲区
intsp;//字符缓冲区指针
charbuf[MAX_FILE];//输入缓冲区
intbp;//输入缓冲区指针
intbuflen;//输入缓冲区长
charch;//当前字符
intline;//当前行
intcol;//当前列
8
ifstreaminFile;//输入文件
ofstreamoutFile,errFile;//输出文件与错误文件
/*---------------私有方法---------------*/
voidScanChar();//扫描下一个字符
voidScanIdent();//扫描标识符
voidScanNumber(intradix);//扫描一个数值
voidScanFraction();//扫描指数
voidScanFractionAndSuffix();//扫描浮点数后缀
voidScanCommentChar();//扫描注释标志
voidScanLitChar();//扫描字符串
voidScanOperator();//扫描运算符
intDigit(intbase);//将ASCII字符转化为数值
voidPutChar(charch);//向字符缓冲区追加一个字符
voidSkipComment();//跳过注释内容
boolIsJavaIdentifierStart(constchar&ch);//是否为Java标识符地首字符
boolIsJavaIdentifierPart(constchar&ch);//判定指定字符是否为Java标识符
中除首字符外地字符
boolIsSpecial(constchar&ch);//是否为特殊字符
voidLexError(constPosition&pos,constchar*msg,constchar*arg);//
错误输出
voidLexError(constPosition&pos,constchar*msg);//错误输出
voidLexError(constchar*msg);//错误输出
voidLexError(constchar*msg,constchar*arg);//错误输出
public:
/*---------------公共属性---------------*/
inttoken;//当前地token
intcount_line;//本行单词数
intcount_file;//整个源文件单词数
/*---------------公共方法---------------*/
Scanner(char*fn_in,char*fn_out,char*fn_err);//构造函数
~Scanner();//析构函数
voidNextToken();//扫描下一个token
voidOutputToken();//输出当前地token
staticintNameToKey(char*msg);//从名称得到详细属性
static