词法分析(一)

合集下载

词法分析详解课件

词法分析详解课件

GitHub仓库
许多开源的自然语言处理工具都在GitHub上托管和分享,可以作 为学习和研究的资源。
在线教程和课程
各大在线教育平台(如Coursera、Udacity等)提供了丰富的自然 语言处理课程,包括词法分析的详细教程。
学术论文
深入研究词法分析的学术论文,可以在各大学术数据库中检索并阅 读。
05 词法分析的挑战与未来发 展
未登录词问题
总结词
未登录词问题是指分词过程中遇到的新词或未知词,无法被正确识别和分割。
详细描述
在自然语言处理中,未登录词问题是一个常见挑战。由于语言的复杂性和动态性,总会有一些新词或未知词出现 ,导致分词器无法正确识别和分割。解决未登录词问题的方法包括基于规则的方法、基于统计的方法和混合方法 等。
促进多任务处理
词法分析的结果可以用于 多种自然语言处理任务, 如分词、词性标注、句法 分析等。
词法分析的基本原则
一致性
对同一类文本的处理方式 应该保持一致,避免出现 不同的分词结果。
准确性
分词结果应尽可能准确, 减少错误和歧义。
高效性
分词算法应尽可能高效, 以满足大规模文本处理的 实时性要求。
02 词法分析的步骤
THANKS FOR WATCHING
感谢您的观看
词义消歧
词义消歧是指在对文本进行分词和词性标注后,对同形异义词和多义词进行语义区分的过程 。
同形异义词是指形式相同但意义不同的词语,例如“银行”既可以指代金融机构,也可以指 代河岸边坡。多义词是指具有多个相关联意义的词语,例如“绿色”可以指颜色,也可以指 环保、生态等意义。
词义消歧的方法可以分为基于规则的方法、基于统计的方法和混合方法三种。基于规则的方 法主要依靠人工制定的消歧规则,而基于统计的方法则通过机器学习算法进行消歧。混合方 法则是将基于规则的方法和法分析是自然语言处理中的重要预 处理步骤,它有助于提高文本处理的 精度和效率,为后续的文本理解和生 成提供准确的基础。

实验一词法分析(单词识别)

实验一词法分析(单词识别)

实验一:词法分析一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

本实验中,采用的是一类符号一种别码的方式。

2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>-> -<大于关系运算符>-> ><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。

如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。

于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。

但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。

在分析标识符,无符号整数等时也有类似情况。

计算语言学讲义(03)词法分析(一)

计算语言学讲义(03)词法分析(一)
计算语言学讲义(04)词法分析I
6
序列标注问题
• 输入:一个符号序列 • 输出:给每一个输入符号赋予一个标记 • 常见具体问题:
– 音字转换:拼音序列 – 词性标注:词语序列 – 词义排歧:词语序列 汉字序列 词性序列 词义标记序列
计算语言学讲义(04)词法分析I
7
序列结构化
• 输入:一个符号序列 • 输出:一个结构,刻划符号之间的关系 • 常见具体问题:
• 输入:一段文本 • 输出:单词串 • 算法:(略)
计算语言学讲义(04)词法分析I
21
Stemming
屈折型语言的词语变化形式: • 屈折变化:即由于单词在句子中所起的语法作用的不同而 发生的词的形态变化,而单词的词性基本不变的现象,如 ( take, took, takes)。识别这种变化是词法分析的最 基本的任务。 • 派生变化:即一个单词从另外一个不同类单词或词干衍生 过来,如morphological morphology,英语中派生变化 主要通过加前缀或后缀的形式构成;在其他语言中,如德 语和俄语中,同时还伴有音的变化。 • 复合变化:两个或更多个单词以一定的方式组合成一个新 的单词。这种变化形式比较灵活,如well-formed, 6year-old等等。 Stemming的目的:将上述变化还原
– 成分句法分析:词语序列 短语结构树 – 依存句法分析:词语序列 依存树 – 语义分析:词语序列 语义网络
计算语言学讲义(04)词法分析I
8
问题与方法
• 计算语言学常用方法:
– 规则方法
• 形式语法理论 • 形式逻辑 • ……
– 统计方法
• • • • n元语法模型 隐马尔科夫模型 最大熵模型 ……
计算语言学讲义(04)词法分析I

词法分析(一):状态转换图

词法分析(一):状态转换图

词法分析(⼀):状态转换图状态转换图状态转换图是⼀张有限有向图结点表⽰状态,结点⽤圆圈表⽰状态之间存在有向弧,弧上标记有字符或字符集,表⽰某⼀状态接受箭弧上的字符/字符集输⼊后到达另⼀状态⼀张状态转换图中的状态个数是有限的,其中有⼀个初态,⾄少有⼀个终态如上图表⽰状态1为初态,状态3为终态,状态1接受字符a到达状态2,接受数字到达状态3终态⽤双圈表⽰状态转换图可⽤于识别 / 接受⼀定的字符串若存在⼀条从初态到某⼀终态的道路,记这条路上所有弧上的标记符连接成的字(即字符串)为α,则称α被该状态转换图识别 / 接受⽐如上⾯的状态转换图,可以⽤来识别以字母开头,可以存在数字的标识符(状态3的*号表⽰,不包含到状态3的弧上的字符)可以识别整常数的状态图状态转换图在词法分析中的应⽤有某种简单的程序设计语⾔,单词表如下该语⾔所有合法的字都在该单词表内描述单词符号种别编码助记符内码值DIM1$DIM—IF2$IF—DO3$DO—STOP4$STOP—END5$END—标识符6$ID内部字符串常数7$INT标准⼆进制形式=8$ASSIGN—+9$PLUS—+9$PLUS—*10$STAR—**11$POWER —,12$COMMA —(13$LPAR —)14$RPAR —单词符号种别编码助记符内码值可为单词表设计如下状态转移图状态2识别关键字和标识符状态4识别常数状态5~12识别操作符和括号状态13为出错状态那么,可以由此图对该语⾔的所有代码进⾏词法分析词法分析器的实现:状态转换图→程序使⽤循环和swith 或if ,我们很容易把上⾯的状态转移图实现为词法分析程序或者使⽤更巧妙的表驱动⽅式当前状态 \ 字符space letter digit =+*,()其他0013567101112131013567101112133444444444478888898888设该数组为state由当前状态cur_state 和读取的字符ch我们可以查表得到下⼀个状态state[cur_state][ch]状态转换图与有限⾃动机可以⽤状态转换图等价表⽰确定有限⾃动机(DFA ) 或者 ⾮确定有限⾃动机(NFA )2019/7/20。

编译原理实验一 词法分析

编译原理实验一 词法分析

实验一词法分析一、实验目的:通过本实验理解词法分析的整个过程,处理对象和处理的结果,了解词法分析在整个编译过程中的作用。

二、实验学时:2学时。

三、实验内容根据给出的简单语言的词法构成规则和单词集合,编制词法分析程序,要求能用给定的简单语言书写的源程序进行词法分析,同时建立相应的符号表文件存放正确的单词。

输出分析结果于文件中,包括:(1)正确的单词符号及其单词种类的序对二元组。

具体输出形式为:二元组:(单词种类,单词内码值)单词种类见五。

四、实验方法构造识别单词集的自动机,编写程序实现。

五、实验的处理单词集(注:单词种类统一分类如下:)七、实验报告要求给出单词识别的状态转换图;带有注释(简单说明)的源程序。

程序运行截图,要求运行结果内有输出自己的名字和学号.状态转换图源程序#include<iostream>#include<string>using namespace std;//单词结构定义struct WordType{int code;string pro;};//关键字表和对应的编码string codestring[6]={"main","int","if","then","else","return"};int codebook[6]={26,21,22,23,24,25};//全局变量char ch;int flag=0;//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str);string concat(string str);//主函数int main(){WordType word;cout<<"请输入源程序列:";word=get_w();while(word.pro!="#")//为自己设置的结束标志{cout<<word.code<<'\t'<<word.pro<<endl;word=get_w();};return 0;}WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){//以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{ wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){//以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='('){ wordtmp.code=1; wordtmp.pro="(";}else if(ch==')'){ wordtmp.code=2; wordtmp.pro=")";}else if(ch=='{'){ wordtmp.code=3; wordtmp.pro="{";}else if(ch=='}'){ wordtmp.code=4; wordtmp.pro="}";}else if(ch==';'){ wordtmp.code=5; wordtmp.pro=";";}else if(ch=='='){ wordtmp.code=6; wordtmp.pro="=";}else if(ch=='+'){ wordtmp.code=7; wordtmp.pro="+";}else if(ch=='*'){ wordtmp.code=8; wordtmp.pro="*";}else if(ch=='>'){ wordtmp.code=9; wordtmp.pro=">";}else if(ch=='<'){ wordtmp.code=10; wordtmp.pro="<";}else if(ch==','){ wordtmp.code=11; wordtmp.pro=",";}else if(ch=='\''){ wordtmp.code=12; wordtmp.pro="\'";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0)//没有回退的字符ch=getchar();else//有回退字符,用回退字符,并重置标志flag=0;}void getBC(){while( ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||(ch>='A'&&ch<='Z'))return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=5;i++){if(codestring[i]==str)//是某个关键字,返回对应的编码return codebook[i];}if(i==6)//不是关键字return -1;}截图实验心得此次实验让我了解了如何设计、编制并调试词法分析程序,并加深了我对词法分析器原理的理解;熟悉了直接构造词法分析器的方法和相关原理。

实验1 词法分析实验报告

实验1  词法分析实验报告
{
p=0;
row=1;
cout<<"Please input string:"<<endl;
do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!='#');
p=0;
do
{
scaner();
switch(syn)
{
case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;
实验二时发现怎么出结果都会出现一个缺:=错误,便回头检查代码才发现实验一时的scaner()函数最后的:和:=的种别码互相写错了,所以回过头来重新修正了代码和实验结果图。
case -1: cout<<"Error in row"<<row<<"!"<<endl; break;
case -2: row=row++;break;
default: cout<<"("<<syn<<","<<token<<")"<<endl;break;
}
}
while (syn!=0);
}
四、结果验证
{
syn=21;
token[m++]=ch;
}
else if(ch=='=')

现代汉语词法分析知识点整理

现代汉语词法分析知识点整理

现代汉语词法分析知识点整理词法分析是现代汉语语法研究的重要组成部分,它主要关注词的构成、分类、形态变化以及词的语法功能等方面。

以下是对现代汉语词法分析的一些关键知识点的整理。

一、词的构成(一)单纯词单纯词是由一个语素构成的词。

单纯词又可以分为以下几类:1、单音节单纯词,如“天”“地”“人”“走”“跑”等。

2、多音节单纯词:联绵词,包括双声联绵词(如“伶俐”“蜘蛛”)、叠韵联绵词(如“骆驼”“徘徊”)和非双声叠韵联绵词(如“鸳鸯”“马虎”)。

叠音词,如“猩猩”“姥姥”。

音译外来词,如“咖啡”“沙发”“巧克力”。

(二)合成词合成词是由两个或两个以上语素构成的词。

合成词的构成方式主要有以下几种:1、复合式联合型,如“道路”“骨肉”“国家”。

偏正型,如“冰箱”“红花”“飞快”。

补充型,如“提高”“说服”“船只”。

动宾型,如“司机”“管家”“美容”。

主谓型,如“地震”“月亮”“民主”。

2、附加式前加式(前缀+词根),如“老”(老虎、老师)、“第”(第一、第二)。

后加式(词根+后缀),如“子”(桌子、椅子)、“头”(苦头、甜头)、“儿”(鸟儿、花儿)。

3、重叠式完全重叠式,如“姐姐”“哥哥”“刚刚”。

部分重叠式,如“绿油油”“红彤彤”“白茫茫”。

二、词的分类(一)实词实词能够单独充当句法成分,有词汇意义和语法意义。

实词包括名词、动词、形容词、数词、量词、代词、副词。

1、名词,表示人或事物的名称,如“学生”“书本”“北京”。

2、动词,表示动作、行为、心理活动或存在、变化、消失等,如“跑”“想”“有”“发展”。

3、形容词,表示性质、状态等,如“美丽”“聪明”“高”“大”。

4、数词,表示数目或次序,如“一”“二”“第一”“第二”。

5、量词,表示计算单位,如“个”“只”“条”“把”。

6、代词,能代替实词和短语,如“你”“我”“他”“这”“那”。

7、副词,常修饰、限制动词、形容词,表示程度、范围、时间等,如“很”“都”“已经”“常常”。

词法分析和语法分析1

词法分析和语法分析1

词法分析和语法分析1为了造福⼤众,你懂的⼀.实验⽬的1.创建⼀个词法分析程序,该程序⽀持分析常规语法。

必须使⽤DFA(确定性有限⾃动机)或NFA(不确定性有限⾃动机)来实现此程序。

程序有两个输⼊:⼀个本⽂档,包括⼀组3°语法(正规⽂法)的产⽣式;⼀个源代码⽂本⽂档,包括⼀组需要识别的字符串。

程序的输出是⼀个令牌表,该表由五种token组成:关键词,标识符,常量,限定符和运算符。

2.创建⼀个采⽤LL(1)⽅法或LR(1)⽅法的语法分析程序。

程序的输⼊是⼀个⽂本⽂件包括⼀组的2°⽂法⽣成(上下⽂⽆关⽂法)产⽣式集合和任务1⽣成的token令牌表。

该程序的输出是yes或no,即,这源代码的字符串是否符合这2°语法。

⼆.说明src⾥⾯是源代码,编译需要配置qt环境Executable⾥⾯是编译好的exe⽂件运⾏后:Function Choose底下选择词法分析还是语法分析,词法分析成功后才能分析语法。

Load选项加载测试的代码⽂件,然后选择uage⽂件夹底下词法分析的5个词法规则⽂件,共有常量(⽀持浮点和科学计数法),标识符、关键字、界符和操作符5种词法。

加载完成后没有提⽰,直接点run运⾏,可以看到输出token表,词法分析完成,同⽬录下会⽣成⼀个中间⽂件⽤于保存token。

然后Function Choose切到语法分析,测试代码和token表⾃动填好了,选择load语法规则⽂件,只有⼀个,加载成功后可以看到左下⾓的LR分析表(Action和Goto表合并了)。

然后再run,右下⾓显⽰分析过程,右上⾓显⽰分析结果(yes/no)。

另外,程序不⽀持打开中⽂路径底下的⽂件,⽀持的词法和语法有限。

三.词法词法规则⽂件内容共分为五种,作为词法分析的依据。

1. 常量[const]->'NUMBER'"C""C"->'NUMBER'"C""C"->'.'"G""C"->'e'"E""C"->'E'"E""C"->''"C"->'i'[const]->'.'"D""D"->'NUMBER'"G""G"->'NUMBER'"G""G"->'e'"E""G"->''"G"->'i'"E"->'+'"H""E"->'-'"H""E"->'NUMBER'"I" "H"->'NUMBER'"I" "I"->'NUMBER'"I" "I"->''"I"->'i'2. 标识符[identifier]->'LETTER' [identifier]->'LETTER'"L" "L"->'LETTER'"L" "L"->'NUMBER'"L" "L"->'LETTER' "L"->'NUMBER'3. 界符[limiter]->';' [limiter]->',' [limiter]->'(' [limiter]->')' [limiter]->'{' [limiter]->'}' [limiter]->','4. 关键字[keyword]->'void' [keyword]->'int' [keyword]->'double' [keyword]->'char' [keyword]->'if' [keyword]->'else' [keyword]->'for' [keyword]->'break' [keyword]->'continue' [keyword]->'return'5. 操作符[operator]->'+' [operator]->'-'[operator]->'/'[operator]->'%'[operator]->'='[operator]->'<'[operator]->'>'[operator]->'+'"op"[operator]->'-'"op"[operator]->'*'"op"[operator]->'/'"op"[operator]->'%'"op"[operator]->'='"op"[operator]->'<'"op"[operator]->'>'"op""op"->'='[operator]->'+'"A""A"->'+'[operator]->'-'"S""S"->'-'四.语法[START]->"X""X"->'@'"X"->"FUN""X""STYLE"->'void'"STYLE"->'int'"FUN"->"STYLE"'identifier''('')''{'"STATEMENTS"'}' "FUN"->"STYLE"'identifier''('"PRALIST"')''{'"STATEMENTS"'}' "PRALIST"->"PRA""EXRTA""EXRTA"->','"PRA""EXRTA"->'@'"PRA"->"STYLE"'identifier' "CALLPRALIST"->"VALUE""EXRTAB" "EXRTAB"->'@'"EXRTAB"->','"VALUE""BLOCK"->'{'"STATEMENTS"'}' "STATEMENTS"->'@' "STATEMENTS"->"STATEMENT""STATEMENTS""STATEMENT"->"EXPRESSION"';'"STATEMENT"->"DEFINE"';'"STATEMENT"->'identifier''('')'';'"STATEMENT"->'identifier''('"CALLPRALIST"')'';'"STATEMENT"->"BRANCH""STATEMENT"->'return'';'"STATEMENT"->'return'"EXPRESSION"';'"BRANCH"->'if''('"EXPRESSION"')'"BLOCK""EXPRESSION"->"VALUE"'operator'"VALUE""EXPRESSION"->"VALUE"'operator'"VALUE""VALUE"->'('"EXPRESSION"')'"VALUE"->'identifier'"VALUE"->'const'"DEFINE"->"STYLE"'identifier'"DEFINE"->"STYLE"'identifier''operator'"EXPRESSION""BLOCK"->"STATEMENT""BLOCK"->'{'"STATEMENTS"'}'五.模块设计以及程序主要代码1.分析器主要流程:2.模块设计:主函数模块:程序开始,设计简单,主要调⽤窗体模块;窗体模块:主要分为两部分,⼀是窗⼝的设计部分,定义页⾯分布以及功能按钮的实现,创造界⾯,⼆是调⽤功能函数;功能函数模块:功能函数分别是词法分析和语法分析,语法分析建⽴在词法分析基础上,需要先进⾏词法分析。

词法分析(一)

词法分析(一)
第3章 词法分析(一)
2012-12-5
莆田学院许振和
1
本章要求

主要内容:词法分析的任务,手工 实现词法分析程序,正规式与有穷 自动机,词法分析程序的自动生成 重点掌握:词法分析器的功能和接 口,用状态转换图设计和实现词法 分析程序,正规文法、正规式和有 穷状态自动机的概念及相互转换

2012-12-5
2012-12-5 莆田学院许振和
12
5. 词法错误处理
词法分析器根据各类单词的构词规则分离、 识别单词符号,所以它只对源程序进行非常局部 的检查,仅能发现非法的单词符号。 词法分析器也可以采用下列可能的错误恢 复动作:
(1)删除一个多余的字符; (2)插人一个遗漏的字符; (3)用一个正确的符号代替一个不正确的符号; (4)交换两个相邻的字符。
2012-12-5
莆田学院许振和
23
某简单语言的词法 分析程序的实现 状态转换图的实 现:使用一个 switch case 语 句:每条分支对 应一个case语句 段
2012-12-5
莆田学院许振和
24
词法分析器的自动生成

正规式 正规文法 有穷自动机
见第3章 词法分析(二)
2012-12-5 莆田学院许振和
/ 处理注释和除 号hand_com() 除 号 Y Y
其它特殊符号 识别界符 recog_del()
在界符表中? isdelimete(s) N 出错处理 error()
Y
插入token表
2012-12-5
ins_token(s,token) 莆田学院许振和
19

识别单词前作如下假定:

关键字就是保留字

词法分析实验报告(实验一)

词法分析实验报告(实验一)

编译原理词法分析实验报告软工082班兰洁200831104044一、实验内容二、实验目的三、实验预期四、程序规定五、实验原理●程序流程图●判别浮点功能扩展流程图●状态转换图六、程序代码与浮点判别功能扩展七、测试用例●扩展功能测试用例;●普通功能测试用例八、输出结果九、实验心得一、实验内容:词法分析:1、识别简单语言的单词符号;2、识别关键字、标识符、数字、运算符等。

并扩展浮点识别功能。

二、实验目的调试词法分析程序,加深对词法分析原理的理解,掌握编写简单词法分析程序的一般步骤。

三、实验预期结果:经过调试源代码程序,程序能够成功运行编译,对输入的简单字符串,能够别关键字、标识符、数字、运算符等,并且给出单词符号的对应编码。

四、程序规定:1、关键字:"function","if","then","while","do","endfunc";2、算术运算符:”+”,”-”,”*”,”/”,”=”;3、关系运算符:"<" ">" "<=" ">=" "==" "!=";4、界符:"(" ")" ";" "#";5、标识符规定以字母开头,字母均为小写;6、空格和换行符跳过;7、单词对应编码:十、实验原理:输入串--------------------〉词法分析程序————————〉单词符号串输入:字符串以#结束。

输出:单词的二元组(syn,token/sum)程序流程图分析浮点数功能扩展部分流程图:shuzi()函数状态转换图六、程序代码:备注:红色字体部分为程序功能的功能扩展,使程序能够分析浮点数!我把浮点数的syn设置为80!/*词法分析源代码*/#include<stdio.h>#include<string.h>scaner();char prog[80],token[8];char ch;int syn,p,m,n,sum;char * rwtab[6]={"function","if","then","while","do","endfunc"}; int i=0,k,c,sumint,f;char fenshu[80],sum1[80];double sumf=0,fudian;int shuzi(){if(ch>='0' && ch<='9')syn=80;elsesyn=-2;return syn;}main(){p=0;printf("\n please input string :\n");do{scanf("%c",&ch);prog[++p]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){ case 11:printf("\n(%d,%d)",syn,sum);break;case -1:printf("\n error");break;case 80:printf("\n(%d,%f)",syn,fudian);break; default:printf("\n(%d,%s)",syn,token);}}while(syn!=0);}scaner(){for(n=0;n<8;n++)token[n]=NULL;//if(1+2!=3)ch=prog[++p];while(ch==' ' || ch=='\n')ch=prog[++p];//跳过空格if(ch>='a' && ch<='z'){m=0;while(ch>='a' && ch<='z' || ch>='0' && ch<='9') {token[m++]=ch;//token[0]=f,m=1ch=prog[++p];}token[m]='\0';ch=prog[--p];syn=10;for(n=0;n<6;n++){if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}}elseif(ch>='0' && ch<='9'){c=p;k=0;do{ sum1[k]=ch;ch=prog[++c]; //ch取后一个数字k++;shuzi();//这个函数用来分析浮点数的整数部分是否已经输入到数组里f=syn;} while(f==80)if(ch=='.'){for(n=0;n<k;n++){sumint=sumint*10+sum1[n]-'0';} //计算整数部分i=0;do{ch=prog[++c];fenshu[i]=ch;i++;shuzi();//这个函数用来分析浮点数的小数部分是否已经输入到数组里} while(syn==80);sumf=0;for(k=i-2;k>=0;k--){sumf=sumf*0.1+(fenshu[k]-'0')*0.1;} //计算浮点数的小数部分fudian=sumint+sumf; //浮点数计算syn=80;p=--c;}else{ch=prog[p];//若是整数,ch等于原来的值 sum=0;while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=prog[++p];}ch=prog[--p];syn=11;}}elseswitch(ch){case'<':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=22;token[m++]=ch;}elseif(ch=='>'){syn=21;token[m++]=ch;}else{syn=20;ch=prog[--p];}break;case'>':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;ch=prog[--p];}break;case'=':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=25;token[m++]=ch;}else{syn=18;ch=prog[--p];}break;case'!':m=0;token[m++]=ch;ch=prog[++p];if(ch=='='){syn=22;token[m++]=ch;}else{syn=-1;p--;}break;case'+':syn=13;token[0]=ch;break;case'-':syn=14;token[0]=ch;break;case'*':syn=15;token[0]=ch;break;case'/':syn=16;token[0]=ch;break;case';':syn=26;token[0]=ch;break;case'(':syn=27;token[0]=ch;break;case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break;default:syn=-1;}}七、测试用例:补充:功能扩展测试用例:八、程序输出结果:功能扩展测试用例输出结果用例一:用例二:用例三:普通功能测试用例显示结果九、实验心得通过编译原理实验一词法分析实验,使得自己对词法分析的流程有了更深刻的了解,虽然源代码并非由自己设计,但是在调试程序的过程中,尤其是进行测序功能扩展的过程中,想了很多种办法,终于找到了最合适的方法,而且还进行了代码的优化,这个过程虽然有时有些枯燥,但是更多时候是欣喜的,不仅复习了c语言的许多内容,并且有了更深的理解。

编译原理词法分析习题集带答案

编译原理词法分析习题集带答案

编译原理词法分析习题集带答案《编译原理》习题(⼀)——词法分析⼀、就是⾮题(请在括号内,正确得划√,错误得划×)1.编译程序就是对⾼级语⾔程序得解释执⾏。

(× )2.⼀个有限状态⾃动机中,有且仅有⼀个唯⼀得终态。

(×)9.两个正规集相等得必要条件就是她们对应得正规式等价。

(× )⼆、选择题1.词法分析器得输出结果就是_____。

A.( ) 记号B.( ) 相应条⽬在符号表中得位置C.( ) 记号与属性⼆元组D.( ) 属性值2. 正规式M 1 与M 2 等价就是指_____。

A.( ) M1与M2得状态数相等B.( ) M1与M2得有向边条数相等C.( ) M1与M2所识别得语⾔集相等D.( ) M1与M2状态数与有向边条数相等3.语⾔就是A.句⼦得集合B.产⽣式得集合C.符号串得集合D.句型得集合4.编译程序前三个阶段完成得⼯作就是A.词法分析、语法分析与代码优化B.代码⽣成、代码优化与词法分析C.词法分析、语法分析、语义分析与中间代码⽣成D.词法分析、语法分析与代码优化5.扫描器所完成得任务就是从字符串形式得源程序中识别出⼀个个具有独⽴含义得最⼩语法单位即A. 字符B.单词C.句⼦D.句型6.构造编译程序应掌握______。

A.( )源程序B.( ) ⽬标语⾔C.( ) 编译⽅法D.( ) 以上三项都就是7.词法分析得任务就是A.识别单词B.分析句⼦得含义C.识别句⼦D.⽣成⽬标代码三、填空题1.计算机执⾏⽤⾼级语⾔编写得程序主要有两种途径:___解释__与__编译___。

3、编译过程可分为( 词法分析) ,(语法分析),(语义分析与中间代码⽣成),(优化)与(⽬标代码⽣成)五个阶段。

6、扫描器得任务就是从( 源程序中)中识别出⼀个个( 单词符号)。

17、⼀张转换图只包含有限个状态,其中有⼀个被认为就是(初)态;⽽且实际上⾄少要有⼀个(终)态。

1.编译程序⾸先要识别出源程序中每个(单词),然后再分析每个(句⼦)并翻译其意义。

广东药学院医药信息工程学院编译原理实验一 词法分析

广东药学院医药信息工程学院编译原理实验一 词法分析

return(es); //返回主程序 } extern int TESTscan(); char Scanin[300],Scanout[300]; FILE *fin,*fout; void main() {
int es=0; es=TESTscan(); if(es>0) printf("词法分析有错,编译停止!"); else printf("词法分析成功!\n"); } 正确分析时截图
token[1]=ch;token[2]='\0'; //组合双分界符结束 ch=getc(fin); //读下一个符号以便识别下一个单词 } else//不是=则为单分界符 token[1]='\0'; fprintf(fout,"%s\t%s\n",token,token); //输出单或双分界符符号 } else if (ch=='/') //注释处理 { ch=getc(fin); //读下一个字符 if (ch=='*') //如果是*,则开始处理注释 { char ch1; ch1=getc(fin); //读下一个字符 do { ch=ch1;ch1=getc(fin);} //删除注释 while ((ch!='*' || ch1!='/')&&ch1!=EOF); //直到遇到注释结束符*/或文件 尾 ch=getc(fin);//读下一个符号以便识别下一个单词 } else //不是*则处理单分界符/ {
实验一 词法分析
实验目的:
1. 熟悉给定的词法分析程序; 2. 改进词法分析程序。
实验内容:
1.熟读给出的词法分析程序 TESTscan.c,理解程序设计内容。 2.尝试多方面改进此 Test 语言的文法,从而尝试在此词法分析程序的基础上改进程序, 并编程运行。参考第三章习题 6

编译原理实验一 词法分析

编译原理实验一     词法分析

实验一词法分析一、实验目的:编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

二、实验内容:如源程序为C语言。

输入如下一段:main(){int a=-5,b=4,j;if(a>=b)j=a-b;else j=b-a;}要求输出如图:(2,”main”)(5,”(”)(5,”)”)(5,”{”)(1,”int”)(2,”a”)(4,”=”)(3,”-5”)(5,”,”)(2,”b”)(4,”=”)(3,”4”)(5,”,”)(2,”j”)(5,”;”)(1,”if”)(5,”(”)(2,”a”)(4,”>=”)(2,”b”)(5,”)”)(2,”j”)(4,”=”)(2,”a”)(4,”-”)(2,”b”)(5,”;”)(1,”else”)(2,”j”)(4,”=”)(2,”b”)(4,”-”)(2,”a”)(5,”;”)(5,”}”)在示例程序的基础上,增加对自加、自减、正负号的判断。

三、源程序:#include<iostream>using namespace std;FILE *fp;char cbuffer;char *key[8]={"if","else","for","while","do","return","break","continue"};int atype,id=4;int search(char searchchar[ ],int wordtype) /*判断单词是保留字还是标识符*/{int i=0;int p;switch (wordtype){case 1:for (i=0;i<=7;i++){if (strcmp(key[i],searchchar)==0){ p=i+1; break; } /*是保留字则p为非0且不重复的整数*/ else p=0; /*不是保留字则用于返回的p=0*/}return(p);}}char alphaprocess(char buffer){ int atype; /*保留字数组中的位置*/int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))||buffer=='_'){alphatp[++i]=buffer;buffer=fgetc(fp);} /*读一个完整的单词放入alphatp数组中*/alphatp[i+1]='\0';atype=search(alphatp,1);/*对此单词调用search函数判断类型*/if(atype!=0){ printf("%s, (1,%d)\n",alphatp,atype-1); id=1; }else{ printf("(%s ,2)\n",alphatp); id=2; }return buffer;}char digitprocess(char buffer){int i=-1;char digittp[20];while ((isdigit(buffer))){digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';printf("(%s ,3)\n",digittp);id=3;return(buffer); }char otherprocess(char buffer){char ch[20];ch[0]=buffer;ch[1]='\0';if(ch[0]==','||ch[0]==';'||ch[0]=='{'||ch[0]=='}'||ch[0]=='('||ch[0]==')') { printf("(%s ,5)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='*'||ch[0]=='/'){ printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='='||ch[0]=='!'||ch[0]=='<'||ch[0]=='>'){ buffer=fgetc(fp);if(buffer=='='){ ch[1]=buffer;ch[2]='\0';printf("(%s ,4)\n",ch);}else {printf("(%s ,4)\n",ch);id=4;return(buffer);}buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='+'||ch[0]=='-'){if(id==4){ /*在当前符号以前是运算符,则此时为正负号*/ int i=1;buffer=fgetc(fp);ch[1]=buffer;ch[2]='\0';if(ch[0] == ch[1]){printf("(%s,3)\n",ch);buffer=fgetc(fp);return buffer;}while(isdigit(ch[i])){ch[++i] = fgetc(fp);}ch[i] = '\0';id=3;printf("(%s ,3)\n",ch);return(buffer);}buffer=fgetc(fp);ch[1]=buffer;if(ch[0] == ch[1]){ch[2]='\0';printf("(%s,3)\n",ch);buffer=fgetc(fp);return buffer;}ch[1]='\0';printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}}void main(){if ((fp=fopen("example.c","r"))==NULL) /*只读方式打开一个文件*/ printf("error");else{cbuffer = fgetc(fp); /*fgetc( )函数:从磁盘文件读取一个字符*/while (cbuffer!=EOF){if(cbuffer==' '||cbuffer=='\n') /*掠过空格和回车符*/cbuffer=fgetc(fp);elseif(isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);elseif (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);else cbuffer=otherprocess(cbuffer);}}system("pause");}四、实验运行结果:五、实验心得:通过这次实验,更加深了我对编译中的词法分析过程的理解,我将老师所给的示例加以修改,添加了++,--,以及正负号的判断,虽然还有很多实际问题没有考虑进去,例如程序中若有‘//’或者‘/*..*/’时则无法判断出解释语句。

03第3章 词法分析1

03第3章 词法分析1
正则表达式的部分操作符满足结合律、交换律和分配律: 即 (ab)c=a(bc) (a|b)|c=a(b|c) a|b=b|a a(b|c)=ab|ac 注意:连接不满足交换律,即ab≠ba
3.5.2 正则文法与正则表达式的等价性
正则文法与正则表达式有等价性,即可以将正则文法转换成正则 表达式。 例如,用正则文法表示标识符的文法规则如下: <标识符>∷= a|b|…|z |<标识符>a|<标识符>b|…|<标识符>z |<标识符>0|<标识符>1|…|<标识符>9 而采用正则表达式则为: <标识符>= (a|b|c|…|z){a|b|…|z|0|1|…|9} 或简写成 <标识符>=字母{字母|数字} 由此可见,正则表达式在描述语言时比正则文法更为简洁 由此可见,正则表达式在描述语言时比正则文法更为简洁。
3.5.1 正则表达式定义
3.5.1 正则表达式定义
在正则表达式的运算符中,重复优先级高于连接,而连接高于 选择,因此,(p) | ((p) . (q))可写成p | pq , 但表达式(p|q).r中的括 号则不能去掉。 例3.5,设字母表∑={a,b},则a,b, Φ和ε都是∑上的正则表达式, 所描述的语言为{a}、{b}、{}、{ε},求表达式{a}{b}、{a|b} {aa|ab|ba|bb} 和{aa|ab|ba|bb}定义的语言。 解:根据正则表达式的形式定义,可得如下结果: 表达式{a}{b}定义的语言为:{ambn|m≥0,n≥0}, 表达式{a|b}定义的语言为:{x|x ∈{a,b}*},即字母a或b组成的 任意长度字符串。 而表达式{aa|ab|ba|bb}表示的语言由字母a或b组成的所有偶长 度字符串。
3.5.2 正则文法与正则表达式的等价性
例3.7,有正则文法如下,将其换成 等价的正则表达式。 S → aS S →aB B →bC C →aC C →a 解: 先用元符号“{”和“}”将文法改 写成如下: S={a}aB B =bC C = {a}a 然后按解方程组的方法可得: C={a}a B= b{a}a S={a}ab{a}a 最终转成正则表达式 S={a}ab{a}a 可以验证,它表示的语言与原来 的正则文法描述的语言相同。

实验一(词法分析)1

实验一(词法分析)1

实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。

2、深刻领会状态转换图的含义,逐步理解有限自动机。

3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。

二.实验内容TINY计算机语言的编译程序的词法分析部分实现。

从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。

为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。

(2)空白符仅仅是空格、回车符、制表符。

(3)代码是自由格式。

(4)注释应放在花括号之内,并且不允许嵌套三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符 (空格、回车符、制表符)(4)列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误,词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。

(2)词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。

这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。

(3)标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。

源程序:/*注意:测试时把测试的源程序存入当前目录中,并改名为source.txt*/ #include<iostream> #include<iomanip> #include<ctype.h> #include<fstream>#include<string>using namespace std;enum WordType {WRONG, NUMBER, BIAOSHI, IF, THEN, ELSE, END, REPEAT, UNTIL, //9READ, WRITE, PLUS, SUBTRACT, MULTIPLY, DIVIDEY, EQUAL, LESSTHAN, COLON,//18ASSIGNMENT, LINE_FEED, SPACE, TAB, BRACKET_L, BRACKET_R}; //24enum CharType {ALPHABET, OTHER};enum WrongType {ZERO, ALP_NUM, NUM_ALP, UNLEAGL_S, NO_MATCH, UNKNOW};char*Words [] = {"wrong", "number", "biaoshi", "if", "then", "else", "end", "repeat", "until", //9"read", "write", "+", "-", "*", "/", "=", "<", ":",//18 ":=", "\n", " ", " ", "{", "}"}; //24typedef struct{char *str;int wordtype;}Two;char ArrayChar[100], cbuffer;int i=-1, numline = 1, wordtype;string LineChar;Two T;ifstream fp("source.txt",ios::in);int main (){void HandleAlphabet();void HandleNumber ();void HandleOther ();if (!fp)cout<<"文件打开错误!!"<<endl;else{cout << setiosflags (ios::left) << setw (6) << "行数" << "(";cout << setiosflags (ios::left) << setw (10)<< "类别编码" << ", ";cout << setiosflags (ios::left) << setw (20) << "字符" << ")" << endl;fp.get (cbuffer);while (!fp.eof ()){if(cbuffer == '\n')//忽略换行符{cout << "第"<< numline << " 行所有字符:" << LineChar << endl;numline++;LineChar = "";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略空字符{LineChar += " ";fp.get(cbuffer);}else if (cbuffer == ' ')//忽略制表符{LineChar += " ";fp.get(cbuffer);}else if (isalpha(cbuffer))//判断是否是字母{HandleAlphabet ();}else if (isdigit(cbuffer))//判断是否是数字{HandleNumber ();}else//其他字符HandleOther ();i = -1;}}cout << "第" << numline << " 行所有字符:" << LineChar << endl;fp.close ();system ("pause");return 0;}int Match(char str[], int chartype)//查找匹配的字符{int i;switch (chartype){case ALPHABET:for (i = IF; i <= WRITE; i++){if (strcmp(Words[i],str) == 0)return i;}case OTHER:for (i = PLUS; i <= ASSIGNMENT; i++){if (strcmp(Words[i],str) == 0)return i;}}return WRONG;}void TypeWrong (int wrongtype, int line){switch (wrongtype){case ZERO:break;case ALP_NUM:cout << "字母后面不能紧跟数字!";break;case NUM_ALP:cout << "数字后面不能紧跟字母!";break;case UNLEAGL_S:cout << "非法特殊符号!";break;case NO_MATCH:cout << "没有与第" << line << " 行“{”匹配的“}”!";break;default :cout << "其它类型错误!";break;}}Two ConvertTwo (char str[], int wordtype, int wrongtype, int numline, int line)//进行二元转换{Two T;T.wordtype = wordtype;T.str = str;cout << setiosflags (ios::left) << setw (6) << numline << "(";cout << setiosflags (ios::left) << setw (10) <<T.wordtype << ", ";cout << setiosflags (ios::left) << setw (20) << T.str << ")";if (T.wordtype == WRONG)TypeWrong (wrongtype, line);cout << endl;return T;}void HandleAlphabet ()//首字符为字母时的处理{bool mark = true;while(!fp.eof() && isalpha(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isdigit (cbuffer)){mark = false;while(!fp.eof() &&(isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark){wordtype = Match(ArrayChar, ALPHABET);T = ConvertTwo(ArrayChar,(BIAOSHI > wordtype ? BIAOSHI : wordtype), ZERO, numline, numline);}elseT = ConvertTwo(ArrayChar,WRONG, ALP_NUM, numline, numline);}void HandleNumber ()//首字符为数字时的处理{bool mark = true;while (!fp.eof() && isdigit(cbuffer)){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}if (isalpha(cbuffer)){mark = false;while(!fp.eof() &&(isalpha(cbuffer)||isdigit(cbuffer))){ArrayChar[++i]=cbuffer;fp.get(cbuffer);}}ArrayChar[i+1]='\0';LineChar += ArrayChar;if (mark)T = ConvertTwo(ArrayChar, NUMBER, ZERO, numline, numline);elseT = ConvertTwo(ArrayChar,WRONG, NUM_ALP, numline, numline);}void DeleteNote ()//删除注释{int record = numline;while (!fp.eof() && cbuffer != '}'){fp.get(cbuffer);while (!fp.eof() && cbuffer != '}'){if (cbuffer == '\n'){ArrayChar [i + 1] = '\0';LineChar += ArrayChar;cout << "第"<< numline << " 行所有字符:" << LineChar << endl;LineChar = "";numline++;i = -1;fp.get(cbuffer);}ArrayChar[++i]=cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';if (cbuffer == '}'){ArrayChar [++i] = '}';ArrayChar[i + 1]='\0';T = ConvertTwo("}", BRACKET_R, ZERO, numline, numline);}else{T = ConvertTwo("", WRONG, NO_MATCH, numline, record);}}LineChar += ArrayChar;fp.get(cbuffer);}void HandleOther ()//字符为特殊字符时的处理{ArrayChar [++i] = cbuffer;if (ArrayChar [i] == '{')//删除注释{ConvertTwo("{", BRACKET_L, ZERO, numline, numline);DeleteNote ();}else//其他字符{fp.get(cbuffer);while (!fp.eof() && cbuffer != '\n' && cbuffer != ' ' && cbuffer != ' ' && !isalpha(cbuffer)&& !isdigit(cbuffer)){ArrayChar [++i] = cbuffer;fp.get(cbuffer);}ArrayChar[i + 1]='\0';wordtype = Match(ArrayChar, OTHER);LineChar += ArrayChar;T = ConvertTwo(ArrayChar, wordtype, (wordtype > 0 ? 0: UNLEAGL_S), numline, numline);}}。

工学第四章词法分析1课件

工学第四章词法分析1课件

内部字符串
整数值
数值
0或1 内部字符串
-
-
-
-
…..
-
-
-
-- 6/47
计算机教研室
考虑下述C++代码段:while (i>=j) i--; 经词法分析器处理后,它将被转换为如下的单词符号 序列: <while, -> <(,-> <id,指向i的符号表项的指针> <>=,-> <id,指向j的符号表项的指针> <),-> <id,指向i的符号表项的指针> <--,-> <;,->
点,另一个为句末符。所以一直搜索到这里 才能区分开1 句是DO语句,3语句是赋值句。 语句2、4主要区别在于右括号之后的第一个字符:一个 为字母,另一个为等号。所以也只能搜索到该字符才能得 到语句2是IF语句,语句4是赋值句。
2024/7/22
第四章:词法分析
12/47
计算机教研室
4.2单词的描述工具
的值。标识符单列一种。常数按类型分种类。
2024/7/22
第四章:词法分析
4/47
计算机教研室
1)按单词种类分类
单词名称
类别编码 单词值
标识符
1
无符号常数(整)
2
无符号浮点数
3
布尔常数
4
字符串常数
5
保留字
6
分界符
7
2024/7/22
第四章:词法分析
内部字符串 整数值 数值 0或1 内部字符串 保留字或内部编码 分界符或内部编码
任何a∈Σ, a是Σ上的一个正规式,它所表示的正规集为

词法分析

词法分析

第一章词法分析本章主要掌握下面一些内容。

1.词法分析器的作用和接口,用高级语言编写词法分析器等内容,它们与词法分析器的实现有关。

(我们没有安排这方面的习题,因为大部分教材上都有这方面的例子)。

2.掌握下面涉及的一些概念,它们之间转换的技巧、方法或算法。

∙非形式描述的语言↔正规式(↔表示两个方向的转换都要掌握)∙正规式→ NFA(非确定的有限自动机)∙非形式描述的语言↔ NFA∙ NFA → DFA(确定的有限自动机)∙ DFA →最简DFA∙非形式描述的语言↔ DFA(或最简DFA)1.1.叙述正规式(00 | 11)*( (01 | 10) (00 | 11)* (01 | 10) (00 | 11)* )*描述的语言。

答案该正规式所描述的语言是,所有由偶数个0和偶数个1构成的串。

另外,和该正规式等价的正规式有( 00 | 11 | ( (01 | 10) (00 | 11)* (01 | 10) ) )*。

分析叙述正规式描述的语言并没有一种统一的办法,只能是通过对正规式的具体分析去总结。

该正规式的一个重要特点是,它是两个字符一组来考虑的。

正规式(00 | 11)*表示的串的长度是偶数,每两个字符一组的话,不是00就是11。

再看正规式(01 | 10) (00 | 11)* (01 | 10),它表示的串由01或10开始,中间有若干组00或11,最后出现01或10。

这样的串仍然由偶数个0和偶数个1构成,只不过第一组是01或10的话,那么一定还要有一组01或10才能保证它们的偶数性。

显然,正规式(01 | 10) (00 | 11)* (01 | 10) (00 | 11)*表示的串也仍然是由偶数个0和偶数个1构成。

这样,可以判断题目所给的正规式表示的语言的每个句子都是由偶数个0和偶数个1构成。

反过来还需要考虑,任何由偶数个0和偶数个1构成的串是否都在这个语言中。

这实际上是问,每个这样的串,其结构是否都符合正规式(00 | 11)*( (01 | 10) (00 | 11)* (01 | 10) (00 | 11)* )*所做的刻划。

实验一:词法分析JN

实验一:词法分析JN

实验一:词法分析一、实验目的给出PL/0文法规范,要求编写PL/0语言的词法分析程序。

二、实验准备微机CPU主频1.3G以上,128M内存,安装好C语言,PASCAL语言,或C++。

三、实验时间6学时四、实验内容已给PL/0语言文法,输出单词(关键字、专用符号以及其它标记)。

二.实验内容1、格式输入:源程序文件。

输出:关键字、专用符号以及其它标记。

2、编译对象:包含如下基本内容 1)变量说其它标记: 明语句 2)赋值语句 3)条件转移语句 4)表达式(算术表达式和逻辑表达式) 5)循环语句 6)过程调用语句3、实现过程本次实验所用的语言为标准C,以下同。

本功能实现的主函数为getToken函数。

通过从文件中读取字符到缓冲区中并由C语言字符的状态转换图流程判断返回一个字符(Token)。

分析出来的Token主要分为关键字,专用符号,标记符号。

本实验实现的C语言的基本词法如下:关键字: els if int return void while专用符号: + - * / < >= == != = ; , ( ) [ ] { } /* */其它标记: id numID = letter letter*NUM = digit digit*letter = a|b|...|z|A|B|...|Z|ditit= 0|1|...|9通过在C语言中定义一个枚举类型来识别这些符号:PL/0语言的EBNF表示<常量定义>::=<标识符>=<无符号整数>;<标识符>::=<字母>={<字母>|<数字>};<加法运算符>::=+|-<乘法运算符>::=*|/<关系运算符>::==|#|<|<=|>|>=<字母>::=a|b|…|X|Y|Z<数字>::=0|1|2|…|8|94、主体结构的说明在这里说明部分告诉我们使用的LETTER,DIGIT, IDENT(标识符,通常定义为字母开头的字母数字串)和STR(字符串常量,通常定义为双引号括起来的一串字符)是什么意思.这部分也可以包含一些初始化代码.例如用#include来使用标准的头文件和前向说明(forward ,references).这些代码应该再标记"%{"和"%}"之间;规则部分&gt;可以包括任何你想用来分析的代码;我们这里包括了忽略所有注释中字符的功能,传送ID名称和字符串常量内容到主调函数和main函数的功能.5、实现原理程序中先判断这个句语句中每个单元为关键字、常数、运算符、界符,对与不同的单词符号给出不同编码形式的编码,用以区分之。

实验一词法分析(识别器的实现)

实验一词法分析(识别器的实现)

实验1识别器的实现1.实验目的:掌握简单识别程序的分析、设计与实现的基本技术与一般方法。

2.实验题目:(1)假设一个语言允许使用十六进制数,其规定是:必须以数字打头,必须以H结尾,数中允许使用的字母为A,B,C,D,E, F(分别表示10~15)。

该语言的标识符为字母开头的字母数字串。

试设计一个DFA,使它能识别标识符、无符号的十进制和十六进制整数(假定各单词之间用界限符或空格分开),并编制相应的识别程序。

输入:学生自行确定符号串的输入形式,如键盘输入、文本文件、字符数组等。

输出:标识出规范的符号串与不合规范的符号串。

3.实验要求:(1)上机前编写完整的实验报告,报告中要体现分析→设计→实现等几个过程;如无实验报告,则取消本次上机资格,实验成绩以0分记。

(2)严禁相互抄袭,否则实验成绩以0分记;(3)有完整的源代码,源码有规范的注释,无明显的语法错误;(4)实验报告必须是手写稿(包括源代码),要求书写工整,清晰有条理。

(5)不符合以上(3)、(4)要求者,扣除相应的实验分数。

4.实验步骤(1)分析与设计a)根据给定的语言求出其文法因为该语言的十六进制数,其规定是:必须以数字打头,必须以H结尾,数中允许使用的字母为A,B,C,D,E, F(分别表示10~15)。

该语言的标识符为字母开头的字母数字串。

则可得出该语言的文法可表示如下:S →X’|Y’|Z’(标识符) X’ →P’|P’M’P’ →β|γM’→α|β|γ|αM’|βM’|γM’(无符号十进制) Y’ →α|αY’(十六进制) Z’ →αH|αQ’H Q’→α|β|αQ’ |βQ’α= 0|1| 2|3|4|5|6|7|8|9β = 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|G|H|I|G|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Zb)将该文法转换成正规式由a)小题中M’ →α|β|γ|αM’|βM’|γM’表示为M’→(α|β|γ)*(α|β|γ)Y’ →α|αY’表示为Y’ →α*αQ’→α|β|αQ’ |βQ’表示为Q’→(α|β)*(α|β)则转换成正规表达式为:S= (β|γ) |(β|γ) (α|β|γ)*(α|β|γ) |αH | α(α|β)*(α|β)H |α*αc)由正规式构造NFA初始的NFA图下所示:图1 初始NFA图经过替换规则替换后得到的最终NFA图如下所示:图2 最终的NFA图d)将NFA转换成DFA,并将其最小化对应以上的NFA图,我们可用造表法来表示如下:显然,由图可看出,状态2与状态5等价,而状态1与状态3等价,这里省去状态3和状态5,并将所以指向状态3的状态都指向状态1,指向状态5的都指向状态2。

词法分析实验报告(实验一)

词法分析实验报告(实验一)

词法分析实验报告(鲍小伟20032320)一.实验目的:通过设计、编程、调试出一个具体词法分析程序,加深对词法分析原理的理解,掌握其设计方法。

二.实验内容:用C/C++实现对PASCAL的子集程序设计语言的词法识别程序。

三.实验要求与原理:(1)实验要求:将该语言的源程序,即相应字符流转换成内部表示,并对标识符填写相应的符号表供编译程序以后各阶段使用,输出的单词符号格式为二元组(单词种别,单词在标识符表中的地址),标识符表格式有“序号”和“标识符本身的值”两项。

写出设计报告,内容为:状态转换图、单词符号及内部表示、符号表、出错处理、编程方法等。

(2)实验原理:状态转换图:空白8923单词符号及内部表示:标志符表和常数表:void getchar();//将下一输入字符读到ch中,指针后移一字符位置void getbc();//保证ch是一个非空白字符void concat();//将ch连接到字符串stroken的末尾void retract();//置ch为空白字符,指针前移一字符位置int isdigit();//判断是否整数int isletter();//首字母的判断int reserve();//对stroken进行关键字表的查找,返回其编码值int insertid();//将stroken中的标识符插入符号表,返回在符号表中的位置int insertconst();//将stroken中的常数插入常数表,返回在常数表中的位置四.主要源代码:Scanner::Scanner(char str[], int n) //构造函数{strcpy(buffer, str);length = n;i = j = 0;}int Scanner::isdigit()//判断是否整数{if(ch>='0' && ch<='9')return 1;elsereturn 0;}int Scanner::isletter()//首字母的判断{if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))return 1;elsereturn 0;}void Scanner::getchar() //将下一输入字符读到ch中,指针后移一字符位置{ch = buffer[i];i++;}void Scanner::getbc() //保证ch是一个非空白字符{while(ch == ' ')getchar();}void Scanner::concat() //将ch连接到字符串stroken的末尾{strtoken[j] = ch;j++;}void Scanner::retract() //置ch为空白字符,指针前移一字符位置{ch = ' ';i--;}int Scanner::reserve() //对stroken进行关键字表的查找,返回其编码值{int i, flag = 0;for(i=0; i<15; i++){if( strncmp(reservechar[i],strupr(strtoken), j) == 0 ){flag = 1;break;}}if(flag == 1) return i+1;else return 0;}int Scanner::insertid() //将stroken中的标识符插入符号表,返回在符号表中的位置{for(int a = 0; a < m; a++)for(int b = 0; b < x[a]; b++)if( strncmp(&id[a][0], strtoken, j) == 0 ){return m+1;break;}for(a = 0; a < j; a++)id[m][a] = strtoken[a];x[m] = j;m++;return m;}int Scanner::insertconst() //将stroken中的常数插入常数表,返回在常数表中的位置{for(int i = 0; i < j; i++)cst[n][i] = strtoken[i];y[n] = j;n++;return n;}void Scanner::scan(){while(i < length){j = 0;int code, value;strcpy(strtoken, " "); //置strtoken为空串getchar();getbc();if(isletter()) //如果打头的是字母{while(isletter() || isdigit()){concat();getchar();}retract();code = reserve();if(code == 0) //如果扫描到的是标识符{value = insertid();cout<<"<34,"<<value<<">"<<'\n';}else cout<<"<"<<code<<",*>"<<'\n'; //如果扫描到的是关键字}else if(isdigit()) //如果打头的是数字{while(isdigit()){concat();getchar();}retract();value = insertconst();cout<<"<33,"<<value<<">"<<'\n';}else if(ch == '+')cout<<"<16,*>"<<'\n';else if(ch == '-')cout<<"<17,*>"<<'\n';else if(ch == '*')cout<<"<18,*>"<<'\n';else if(ch == '/')cout<<"<19,*>"<<'\n';else if(ch == '=')cout<<"<20,*>"<<'\n';else if(ch == '<'){getchar();if(ch == '>')cout<<"<21,*>"<<'\n';else if(ch == '=')cout<<"<23,*>"<<'\n';else{retract();cout<<"<22,*>"<<'\n';}}else if(ch == '>'){getchar();if(ch == '=')cout<<"<25,*>"<<'\n';else{retract();cout<<"<24,*>"<<'\n';}}else if(ch == '.')cout<<"<26,*>"<<'\n';else if(ch == ',')cout<<"<27,*>"<<'\n';else if(ch == ';')cout<<"<28,*>"<<'\n';else if(ch == ':'){getchar();if(ch == '=')cout<<"<30,*>"<<'\n';else{retract();cout<<"<29,*>"<<'\n';}}else if(ch == '(')cout<<"<31,*>"<<'\n';else if(ch == ')')cout<<"<32,*>"<<'\n';else if(ch == '{'){while(ch != '}')getchar();}else cout<<"出错!"<<'\n';}}void main(void){fstream file;file.open("F:/20032320/20032320.txt", ios::in||ios::nocreate); //以只读方式打开file.unsetf(ios::skipws); //不跳过文本中的空格char buffer[100]; //缓冲区定义cout<<"扫描结果如下所示"<<'\n';while(file.getline(buffer, 100)){Scanner SS(buffer, strlen(buffer));SS.scan();}cout<<"标识符表如下:\n"<<"编号\t"<<"值\n";for(int i=0; i<m; i++){cout<<i+1<<'\t';for(int j=0; j<x[i]; j++)cout<<id[i][j];cout<<'\n';}cout<<"常数表如下:\n"<<"编号\t"<<"值\n";for(i=0; i<n; i++){cout<<i+1<<'\t';for(int j=0; j<y[i]; j++)cout<<cst[i][j];cout<<'\n';}}五.运行结果:程序的运行结果如下图所示:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档