[计算机软件及应用]编译原理实验报告词法分析
学院:计算机科学与技术
时间:2012/6/9
一、 问题描述
选择计算机高级程序语言之一 —— C语言,运用恰当的词法分析技术线路,设
计和实现其对应的词法分析器
提示:技术线路选择如下两种之一:
正则式?NFA?DFA?min DFA?程序设计
或 正则文法?NFA?DFA?min DFA?程序设计。
要求:分析器输出结果存入到磁盘文件中,具有出错处理功能。 二、 系统分析
编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。词法分析阶段是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。词法分析程序实现这个任务。从左到右逐个字符对构成源程序的字符串进行扫描,依据词法规则,识别出一个一个的标记(token),把源程序变为等价的标记串序列。执行词法分析的程序称为词法分析器,也称为扫描器。本次实验,我选择用C++来实现这个词法分析器。
程序语言的单词符号一般分为以下六种:关键字、标识符、常量、运算符、界符、字符串
词法分析程序所输出的单词符号常常采用以下二元式表示:(单词 种别,单词自身的值),单词的种别是语法分析所需要的信息,而单 词自身的值是编译其他阶段需要的信息。
单词的种别可以用整数编码表示,比如标识符编码为 1,程序最 后输出的形式应为:
关键字 int (2 , int )
标识符 t_val (1 , t_val)
常量 3.14e+2 (3 , 3.14e+2) 其中,本次实验设计的如下:
(1)关键字有34个:分别包括
"char","int","short","long","signed","unsigned","float","double","const","void","volatile
","enum","struct","union","typedef","auto","extern","static","register","if","else","swit
ch","case","default","while","do","for","break","continue","goto","return","sizeof","#in
clude","#define"
前面32个是标准C的关键字,后两个是预编译的关键字。
(2)常量分为:小数,整数,浮点数,字符。本次实验中,设计了小数,整数和浮点数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就是‘a’表示的并不是对应的数值。
(3)运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设计进去了。其中包括 +,++,+=, -,-=,->,--, *,*=, /,/=,[,],
<,<=, > , >= ,=,==,>>,>>=,<<,<<=,!=,&,&&,&=,~,|,||,|=,%,%=, ,;
但是还是有个别的运算符没有设计进去,比如,:,这是个三目的运算符,设计起来估计很麻烦,所以就没设计,还有就是强制类型转换(类型),取地址&,指针*,指针的.运算都没有很好的设计思考,都是直接忽略了。
(4)字符串:实验中并没有考虑字符串的读写,直接将他设计成了标识符(5)标识符:除了上述说的,还有就是一些不该出现的符号,比如`@#$等,剩下的基本上都是标识符了。
利用该词法分析器完成对源程序字符串的词法分析。输出形式是源程序的单词符号二元式的代码,并保存到文件中。
根据以上的分类与分析,将该语言中的单词符号及种别编码如下表所示。 单词符号及种别编码
单词符号 种别编码 单词符号 种别编码
char 1 * 54
int 2 / 55
short 3 ( 56
long 4 ) 57
signed 5 [ 58
unsigned 6 ] 59 float 7 { 60 double 8 } 61 const 9 , 62
void 10 : 63 volatile 11 ; 64
enum 12 . 65 struct 13 > 66 union 14 < 67 typedef 15 >= 68
auto 16 <= 69 extern 17 == 70 static 18 != 71 register 19 >> 72
if 20 >>= 73
else 21 << 74 switch 22 <<= 75
case 23 & 76 default 24 && 77 while 25 &= 78
do 26 | 79
for 27 || 80 break 28 |= 81 continue 29 ~ 82
goto 30 ++ 83 return 31 -- 84 sizeof 32 -> 85 #include 33 += 86 #define 34 -= 87 ID标识符 40 *= 88 NUM常量 50 /= 89
= 51 %= 90
+ 52 ^= 91
- 53 % 92
? 95 “ 93
‘ 94
采用的技术路线是正则式?NFA?DFA?min DFA?程序设计
三、 系统设计
l={a~z,A~Z};d={0~9};
1. 关键字:关键字是最好识别的,他都是由字母组成,在程序中,只要写一个小程序将设计的34个关键字保存在一个string类型的vector中,然后做一次循环,将字符串逐个与34个关键字对比,相同则取出对应的种别编码,存入事先设计好的vector中。
本次设计中关键字有34个:分别包括
"char","int","short","long","signed","unsigned","float","double","const","void","vol
atile","enum","struct","union","typedef","auto","extern","static","register","if","els
e","switch","case","default","while","do","for","break","continue","goto","return","
sizeof","#include","#define" 前面32个是标准C的关键字,后两个是预编译的关键字。
2. 标识符:标识符的正规式为:(l|_)(l|d|_)*
对应的NFA为:
l|_
2 1
l|d|_
实际应用到程序上的DFA为:
l|_ 非l|d|_
3 1 2
l|d|_
其中,状态3中代表标识符。事实上,关键字是特殊的标识符,所以首先先将他们归为一类,之后再写程序将其区别,在这里就不画出图了。
3. 常量分为:小数,整数,浮点数,字符。本次实验中,设计了小数,整数和浮点
数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就
是‘a’表示的并不是对应的数值,而是将‘作为符号记录,而将字母a当作了一
个标识符,所以程序写的不是很到位,还有很多小细节上没有很好的处理。
而小数,整数,浮点数这三类我又将他归并后分为了无符号数和有符号数两类。在这里先给出无符号数的正规式和DFA。至于有符号数,除了开始有符号外,之后的判断与无符号数是一致的,所以在这里不在重复的给出,到了+号和—号的时候再给出对应的判断。
无符号数正规式:d(d)*|(d(d)*|ε)(.d(d)*( ε|e(+|-|ε)d(d)*)|e(ε|+|-)d(d)*)
下面给出无符号数的DFA:
d
非l|d|_|.|e d
1 4 5
l|_
6
l|_|. .
7
l|_|.
10 d
8 非l|d|_|.|e
d e
+|-|l|_|.|e +|- 11 9 6
d
d +|-|l|_|.|e
13 12
非+|-|l|_|.|e
d
l|_|e|. l|_|e|.|+|-
d d
14 15 16
e
非+|-|l|_|.|e|d
d +|-
l|_|e|.|+|-
17
解释一下上面图的终结状态:
状态5:表示整数,如123,78等
状态6:表示错误,包括以数字开头字母结尾的错误标识符,有多个小数点的数字,有多个E或e的数字等,这些都是词法错误。
状态10:表示小数,如12.34,7.1等
状态13:表示带有指数前面是小数的数,比如1.2e+12,2.34e14等
状态16:表示带有指数前面是整数的数,如:2e+12,4e11等
上述图中还省略了以小数点或字母e开头的DFA,但是这和上面所画的大同小异,所以在这里就不在重复的给出。画图确实比较麻烦。
至于有符号数,和上面的图实际上相差的也不多,就是在1号状态之前多了一个加号和减号的判断,这里也不再画出。
4. 运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设
计进去了。其中包括
+,++,+=, -,-=,->,--, *,*=,
/,/=,<,<=, > , >= ,=,==,>>,>>=,<<,<<=,!=,&,&&,&=,~,|,||,|=,%,%=,!
但是还是有个别的运算符没有设计进去,比如,:,这是个三目的运算符,设计起来很麻烦,没设计,还有就是强制类型转换(类型),取地址&,指针*,指针的.运算都没有很好的设计思考,都是直接忽略了。
而关于界符,由于没有深入的思考,直接就将下列符号当作一个界符,并没有去考虑他是否还有其余的作用,显得很是粗糙。以下九个符号,都是当作一般符号处理:” , : , „ , [ , ] , { , } , ? , \ 。没有具体的去考虑单个字符如 ?a?表示的实际上是一个数,”0123asd”表示的是字符串(虽然没错,但是自己写的程序却会报错,因为将0123asd当成了一个错误的数字),\n表示的是换行符等等,都没有考虑,所以程序的功能很是简陋。
虽然设计的很简陋,但是除了一般的功能外,还是增加了一些功能的。对于C语言中的两种注释,自己还是花了点功夫的。行注释//与段注释/* */都能识别出来,并将注释的内容屏蔽,而不保存到输出文件中去。
由于设计的粗糙性,事实上,这里的所有运算符与界符,在设计中所用到的DFA都是大同小异的,因为原理都是一模一样的,所以在这里就简单举几个比较典型的例子,既能说明问题,又不会显得理论不足。
+ +
1 2 3
= 此处与前面所画的
4 无符号数判断完全
相同,这里不再画
d 出
5 6
非+|=|d 7
— —
8 9
= 此处与前面所画的
10 无符号数判断完全
相同,这里不再画
d 出
11 12
非—|=|d|> 13
>
14
* =
15 16
非=
17
/ =
18 19
非=
20
! =
21 22
非=
23
= =
24 25
非=
26 ^ =
27 28
非=
29 < =
30 31
< =
32 33
非=
34
非=|<
35 > =
36 37
> =
38 39
非=
40
非=|>
41
% =
42 43
非=
44
& =
45 46
&
47
非=|&
48 | =
49 50
|
51
非=||
52 “
” 53
„
’54
”
,
’55
”
{
’56
”
}
’57
”
[
’58
”
]
’59
”
(
’60
”
)
’61
”
上面设计了各种运算符和界符的处理,这里再介绍一下两种不同注释。
非\n
/ / \n
1 2 3 4
*
* * /
5 6 7
非*|/
非 *
非/|* 8
5. 字符串:在本次实验设计中,并没有将字符串的设计设计出来,所以就不能对字
符串进行识别,所以没有这个功能,只能对符号”进行判断。
至此,整个实验的基本设计已经完成,由于这些图画的都很麻烦,在这里就不在综合的画一次。前面的表述应该是比较清楚的了。所有的细节都要通过编程来实现了。 四、 系统实现
1.程序设计与具体实现:本次实验,我是用的C++语言写的,运用到了C++中自带的也是常用的一些类,如STRING,VECTOR,FSTREAM等。利用C++的好处是,数据结构的定义直接用VECTOR就行了,操作起来很方便,而利用STRING的功能,也使程序中字符串的操作也可以简化一些。
下面是词法分析主程序的流程图:
开始
输入原文件的路径、名称
N
打开文件成功,
Y
将文件中的数据流读入string类型的cstr中保存 循环除去空格,换行,保存标识符、单个运算符、终结符到vector
中
调用扫描分析子程序
scan,将分析结果存
入vector中
Y
是否有错误,
N
调用输出函数,将文件写入
指定的文件中
结束
下面给出简化了的扫描分析子程序的流程图:
开始
i=0
i void main()
{
int a[10];
int i=-10; //abc int y=1.2e+12; /* a+b=c */ void fa(){};
char cha[11]; x+=y;
a->y==c;
while(i)i=i-1; xyz++;
printf("abcdefg"); }
词法分析后的文件:
<33 , "#include"> <67 , "<">
<40 , "stdio.h"> <66 , ">">
<10 , "void"> <40 , "main"> <56 , "(">
<57 , ")">
<60 , "{">
<2 , "int">
<40 , "a">
<58 , "[">
<50 , "10">
<59 , "]">
<64 , ";"> <2 , "int"> <40 , "i"> <51 , "="> <50 , "-10"> <64 , ";"> <2 , "int"> <40 , "y"> <51 , "="> <50 , "1.2e+12">
<64 , ";"> <10 , "void"> <40 , "fa"> <56 , "("> <57 , ")"> <60 , "{"> <61 , "}"> <64 , ";"> <1 , "char"> <40 , "cha"> <58 , "["> <50 , "11"> <59 , "]"> <64 , ";"> <40 , "x"> <85 , "+="> <40 , "y"> <64 , ";"> <40 , "a"> <84 , "->">
<40 , "y">
<70 , "=="> <40 , "c">
<64 , ";">
<25 , "while"> <56 , "(">
<40 , "i">
<57 , ")">
<40 , "i">
<51 , "=">
<40 , "i">
<53 , "-">
<50 , "1">
<64 , ";">
<40 , "xyz"> <82 , "++"> <64 , ";">
<40 , "printf"> <56 , "(">
<92 , """>
<40 , "abcdefg"> <92 , """>
<57 , ")">
<64 , ";">
<61 , "}">
2.)这里再给出出现错误时的截图。本次程序设计,错误又分为两类,一种是出现了
不该有的字符(如`与$),还有一类就是错误的标识符或是错误的常量。
3.源代码
此处将源代码放到最后再给出,以便于后续的阅读。
五、 系统评价
从前面的报告中,可以看出,本次实验的任务(完成一个词法分析器)是基本完成了。主要实现了以下的功能:
1) 对C语言源程序,运用恰当的词法分析路线,将源程序通过分析器的分
析将结果输出存入磁盘文件中;
程序最 后输出的形式应为:
关键字 int (2 , “ int” )
标识符 t_val (1 , “t_val”)
常量 3.14e+2 (3 , “3.14e+2”)
2) 具有一定出错处理功能
虽然完成了这个实验的基本任务,但是从前面的分析中,也可以知道,本次实验在设计的过程中就是很粗糙的,期间忽略了很多问题,下面将问题都一一列出:
(1)设计程序时,关键字设计了34个:其中前面32个是标准C的关键字,后两个是预编译的关键字(这两个并不是标准的关键字)。其实标准的关键字还不止这么几个,这里就没有列出一些少见的关键字,这也不是很重要,写不写的意义都不是很大,所以就这样略过了。
(2)常量分为:小数,整数,浮点数,字符。本次实验中,设计了小数,整数和浮点数,但是都没有包含后面的U,L,UL等标识。而单个字符常量并没有考虑。也就是‘a’表示的并不是对应的数值。
在这里,我在设计的时候就是按无符号数和有符号数来区别的。首先设计的是无符号数,在上面的设计过程中,可以看到这是一个比较复杂的过程,在这种设计下,基本上所有的无符号数我都能识别并分类,但是,设计之前我并没有考虑到这些数的后面可以跟上一些U,L,UL等标识。当我考虑到时,我觉得更改设计会增加很多麻烦,所以直接就忽略了这种情况。对于点开头的数字以及e开头的数字我都是有设计的,但是在编写程序的时候就实现了前面一种,以至于以e开头的常量,在我的词法分析程序中,并不能识别。 而有符号数事实上就是在无符号数上增加一个+或-,有了前面设计的基础,这个设计就很好实现了,在本次实验中还是实现了。
剩下的就还有字符常量了。字符常量考虑的东西是很多的,比如?a?,表示的是一个常量,又如?\0?表示的也是常量,这种常量的多样性导致了设计困难。在此本次实验中,并不能实现相应的功能。
(3)运算符和界符:本次实验设计的运算符和界符很多,基本将所有的运算符都设计进去了。其中包括 +,++,+=, -,-=,->,--, *,*=, /,/=,[,],
<,<=, > , >= ,=,==,>>,>>=,<<,<<=,!=,&,&&,&=,~,|,||,|=,%,%=, ,;
但是还是有个别的运算符没有设计进去,比如,:,这是个三目的运算符,设计起来估计很麻烦,所以就没设计,还有就是强制类型转换(类型),取地址&,指针*,指针的.运算都没有很好的设计思考,都是直接忽略了。 而关于界符,由于没有深入的思考,直接就将下列符号当作一个界符,并没有去考虑他是否还有其余的作用,显得很是粗糙。以下九个符号,都是当作一般
符号处理:” , : , „ , [ , ] , { , } , ? , \ 。没有具体的去考虑单个字符如 ?a?表示的实际上是一个数,”0123asd”表示的是字符串(虽然没错,但是自己写的程序却会报错,因为将0123asd当成了一个错误的数字),\n表示的是换行符等等,都没有考虑,所以程序的功能很是简陋。
虽然设计的很简陋,但是除了一般的功能外,还是增加了一些功能的。对于C语言中的两种注释,自己还是花了点功夫的。行注释//与段注释/* */都能识别出来,并将注释的内容屏蔽,而不保存到输出文件中去。这也是唯一一个不是亮点的亮点了。
(4)字符串:实验中并没有考虑字符串的读写,直接将他设计成了标识符 (5)标识符:除了上述说的,还有就是一些不该出现的符号,比如`@#$等,剩下的基本上都是标识符了。
本次实验,在很大程度上,提高了自己对编译程序的理解。关于c++程序的设计,大多都是使用了相关类的自带函数功能。关于设计的思想,都是个人思考的观点。大致方向上不会出问题的,至于细节,自己也不知道是对是错。虽然程序写的漏洞百出,但是,值得高兴的是大致完成了程序的设计。根据自己的设计思路,程序的思想还是显而易见的。但是可读性估计不是很好,可修改性也很差,代码的编程不够简洁,这些都是实力问题。还需要很多的练习来提高自己。
词法分析器源代码 #include #include #include #include
/* 单词种别码*/
#define _CHAR 1
#define _INT 2
#define _SHORT 3 #define _LONG 4
#define _SIGNED 5 #define _UNSIGNED 6 #define _FLOAT 7 #define _DOUBLE 8 #define _CONST 9 #define _VOID 10 #define _VOLATILE 11 #define _ENUM 12 #define _STRUCT 13 #define _UNION 14 #define _TYPEDEF 15 #define _AUTO 16 #define _EXTERN 17 #define _STATIC 18 #define _REGISTER 19 #define _IF 20
#define _ELSE 21 #define _SWITCH 22 #define _CASE 23 #define _DEFAULT 24 #define _WHILE 25 #define _DO 26
#define _FOR 27
#define _BREAK 28 #define _CONTINUE 29 #define _GOTO 30 #define _RETURN 31 #define _SIZEOF 32 #define _INCLUDE 33 #define _DEFINE 34 /* 以上为关键字的种别码*/
#define _ID 40 //标识符
#define _NUM 50 //数
#define _AS 51 //= #define _PLUS 52 //+
#define _SUB 53 //- #define _TIMES 54 // *
#define _DIV 55 // /
#define _LP 56 // ( #define _RP 57 // ) #define _LB1 58 // [ #define _RB1 59 // ] #define _LB2 60 // { #define _RB2 61 // } #define _COM 62 // , #define _COL 63 // : #define _SEM 64 // ; #define _POINT 65 // . #define _LG 66 // > #define _LT 67 // < #define _ME 68 // >= #define _LE 69 // <= #define _EQ 70 // == #define _NE 71 // != #define _A 72 // >> #define _B 73 // >>= #define _C 74 // << #define _D 75 // <<= #define _E 76 // & #define _F 76 // && #define _G 77 // &= #define _H 78 // | #define _I 79 // || #define _J 80 // |= #define _K 81 // ~ #define _L 82 // ++ #define _M 83 // -- #define _N 84 // -> #define _O 85 // += #define _P 86 // -= #define _Q 87 // *= #define _R 88 // /= #define _S 89 // %= #define _T 90 // ^= #define _U 91 // % #define _V 92 // " #define _W 93 // ' #define _X 94 // ?
#define _EROOR -1 // 错误
using namespace std; int ERROR_NUM=0; //记载词法编译错误个数 bool isnum(string str) // 判断是不是合法的数字 {
int y;
int i;
int j=0;
int k=0;
for(i=0;i='0'))
{
k++;
if((k-j)>1){cout<<"数字串"<1)
{
cout<<"数字串"<='0')&&((str[i+1]<='9'&&str[i+1]>='0')||(y=i+1)==str.size()))
continue;
else{
cout<<"数字串"< ppp(p,p+34);
int u;
for(u=0;u > scan(vector vec)//本次程序的主要分析程序
{
vector > temp;
int i;
for(i=0;i")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_ME,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]==">"&&vec[i+2]!="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_A,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]==">"&&vec[i+2]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
jk.append(vec[++i],0,1);
pair pp(_B,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_LG,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="<")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_LE,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="<"&&vec[i+2]!="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_C,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="<"&&vec[i+2]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
jk.append(vec[++i],0,1);
pair pp(_D,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_LT,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="!")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_LE,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_NE,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="=")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_EQ,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_AS,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="&")
{
if(vec[i+1]=="&")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_F,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_G,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_E,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="|")
{
if(vec[i+1]=="|")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_I,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_J,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_H,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="(")
{
{
pair pp(_LP,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]==")")
{
{
pair pp(_RP,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="[")
{
{
pair pp(_LB1,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="]")
{
{
pair pp(_RB1,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="~")
{
{
pair pp(_K,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]==",")
{
{
pair pp(_COM,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="{")
{
{
pair pp(_LB2,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]==":")
{
{
pair pp(_COL,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]==";")
{
{
pair pp(_SEM,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="}")
{
{
pair pp(_RB2,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="*")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_Q,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_TIMES,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="/")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_R,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="*")
{
i=i+4;
while(i pp(_DIV,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="%")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_S,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_U,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i][0]=='"')
{
pair pp(_V,vec[i]);//标识符
temp.push_back(pp);
}
else if(vec[i][0]=='\'')
{
pair pp(_W,vec[i]);//标识符
temp.push_back(pp);
}
else if(vec[i][0]=='?')
{
pair pp(_X,vec[i]);//标识符
temp.push_back(pp);
}
else if(vec[i]=="+")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_O,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="+")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_L,jk);
temp.push_back(pp);
continue;
}
else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1]))
{
string jk=vec[i];
jk.append(vec[++i]);
pair pp(_NUM,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_PLUS,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i]=="-")
{
if(vec[i+1]=="=")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_P,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]=="-")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_M,jk);
temp.push_back(pp);
continue;
}
else if(vec[i+1]==">")
{
string jk=vec[i];
jk.append(vec[++i],0,1);
pair pp(_N,jk);
temp.push_back(pp);
continue;
}
else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1]))
{
string jk=vec[i];
jk.append(vec[++i]);
pair pp(_NUM,jk);
temp.push_back(pp);
continue;
}
else
{
pair pp(_SUB,vec[i]);//标识符
temp.push_back(pp);
}
}
else if(vec[i][0]<='9'&&vec[i][0]>='0')
{
pair pp(_NUM,vec[i]);
temp.push_back(pp);
}
else
{
pair pp(_ID,vec[i]);//标识符
temp.push_back(pp);
}
}
else if((vec[i][0]<='9'&&vec[i][0]>='0')||vec[i][0]=='.')
{
if(!isnum(vec[i]))ERROR_NUM++;
else if((vec[i+1][0]=='+'||vec[i+1][0]=='-')&&isnum(vec[i+2]))
{
string jk=vec[i];
jk.append(vec[++i]);
jk.append(vec[++i]);
pair pp(_NUM,jk);
temp.push_back(pp);
continue;
}
else{
pair pp(_NUM,vec[i]);
temp.push_back(pp);}
}
else if(iskey(vec[i]))
{
pair pp(iskey(vec[i]),vec[i]);
temp.push_back(pp);
}
else
{
pair pp(_ID,vec[i]);
temp.push_back(pp);
}
}
return temp;
}
void OutFile(vector > v) {
string filename;
cout<<"请输入目标文件的路径及名称:";
cin>>filename;
ofstream outfile(filename.c_str());
if (!outfile)
{
cerr<<"无法打开文件! "<"<
本文档为【[计算机软件及应用]编译原理实验报告词法分析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。