编译原理词法分析器的构造

合集下载

编译原理-实验二-FLEX词法分析器

编译原理-实验二-FLEX词法分析器

编译原理-实验⼆-FLEX词法分析器FLEX词法分析器⼀、Lex和Yacc介绍Lex 是⼀种⽣成扫描器的⼯具。

扫描器是⼀种识别⽂本中的词汇模式的程序。

⼀种匹配的常规表达式可能会包含相关的动作。

这⼀动作可能还包括返回⼀个标记。

当 Lex 接收到⽂件或⽂本形式的输⼊时,它试图将⽂本与常规表达式进⾏匹配。

它⼀次读⼊⼀个输⼊字符,直到找到⼀个匹配的模式。

如果能够找到⼀个匹配的模式,Lex 就执⾏相关的动作(可能包括返回⼀个标记)。

另⼀⽅⾯,如果没有可以匹配的常规表达式,将会停⽌进⼀步的处理,Lex 将显⽰⼀个错误消息。

Yacc代表 Yet Another Compiler Compiler 。

Yacc 的 GNU 版叫做 Bison。

它是⼀种⼯具,将任何⼀种编程语⾔的所有语法翻译成针对此种语⾔的 Yacc 语法解析器。

(下载下载flex和bison。

⽹址分别是/packages/flex.htm和/packages/bison.htm。

)⼆、配置环境(win7)①下载flex和bison并安装到D:\GnuWin32(尽量是根⽬录)②由于我们使⽤的flex和bison都是GNU的⼯具,所以为了⽅便,采⽤的C/C++编译器也采⽤GNU的编译器GCC,当然我们需要的也是Windows版本的GCC了。

所以提前准备好VC 6.0③检验是否可以进⾏lex⽂件编译1.新建⽂本⽂件,更改名称为lex.l,敲⼊下⾯代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2.新建⽂本⽂件,更改名称为yacc.y,敲⼊下⾯代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();}我们暂且不讨论上⾯代码的意思。

打开控制台,进⼊到刚才所建⽴⽂件(lex.l,yacc.y)所在的⽂件夹。

编译原理课程设计-词法分析器

编译原理课程设计-词法分析器

计算机与信息学院编译原理课程设计实验报告专业班级计算机科学与技术专业08-4班学生姓名及学号胡义涛20082645课程教学班号0001任课教师王仲宾实验指导教师王仲宾实验地点逸夫楼5072010~2011 第三学年第一学期一、实验目的和要求:设计并实现一个C语言(或C++语言)的词法分析程序,加深对词法分析原理的理解。

二、试验设计和算法分析:实验原理:程序流程:置初值→调用扫描子程序→输出串结束→输出单词二元组→是→否→结束词法分析主程序示意图待分析的简单语言的词法(1) 关键字:begin if then while do end所有关键字都是小写。

(2)运算符和界符::= + - * / < > <= <> >= ; ( ) #(3)空格由空白、制表符和换行符组成。

词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

三、源代码:#include "stdio.h"#include "string.h"#include "conio.h"#include "ctype.h"char prog[80]={'\0'},token[8]; /*存放构成单词符号的字符串*/char ch;int syn, /*存放单词字符的种别码*/n,sum, /*存放整数型单词*/m,p; /*p是缓冲区prog的指针,m是token的指针*/char*rwtab[6]={"begin","if","then","while","do","end" };void scaner(){m=0;sum=0;for(n=0;n<8;n++){token[n]='\0';}ch=prog[p++];while(ch==' '){ch=prog[p++];}if(isalpha(ch)) //ch为字母字符{while(isalpha(ch)||isdigit(ch))//ch 为字母字符或者数字字符{token[m++]=ch;ch=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(isdigit(ch)) //ch是数字字符{while(isdigit(ch)) //ch是数字字符{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=21;token[m++]=ch;}else if(ch=='='){syn=22;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=18;token[m++]=ch;}else{syn=17;ch=prog[p--];break;case'10':syn=12;token[0]='n';break;case'11':syn=12;token[0]='n';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=25;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;}}main(){printf("\n\n对应信息:\n""1.1-6为关键字\n""2.10-11为字符或常量\n""3.12-28为表示符\n");p=0;printf("\nplease input string:\n");do {ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11: printf("(%d,%d)\n",syn,sum);break;case -1: printf("\n ERROR;\n");break;default: printf("(%d,%s)\n",syn,token); }}while(syn!=0);getch();}四、实验结果及总结:输出:总结:通过该实验,主要有以下几方面收获:一、对实验原理有更深的理解。

编译原理实践5—PL0的词法分析程序构造

编译原理实践5—PL0的词法分析程序构造

辅助过程getch
getsym需要一个辅助过程getch,每被 调用一次就读入下一个字符 除此之外的任务:
识别行结束标志,作为空格符处理 拷贝原文输出 在输出文件每行开始添加坐标(书中例子程 序没有体现)
3.词法分析程序的设计
每调用一次getsym,首先用循环结构在 源程序上向前读入一个非空格字符,然 后对此字符进行分析,转相应部分处理 getsym大致可以分为三个部分
字符语法分析安排在同一遍中
,此时词法分析作为语法分析程序的一个子程序。每 当语法分析需要一个新的符号时,就调用词法分析子 程序,词法分析子程序从字符串源程序中识别出一个 具有独立意义的单词,将其符号返给语法分析。这种 方法避免了中间文件,省去了送取符号工作,有利于 提高编译程序的效率。书中采用这种方案。
取符号
字符串源程序
词法分析器
送符号
语法分析器
程序getsym
本课程采用第2种方案,程序名getsym,预先 审视源程序下一个符号,并将读入的符号放在 变量sym中,语法分析的判断分析将以这个读 入的符号为基础 具体任务:
跳过空格字符 识别像begin、end、if、while等这样的保留字 识别非保留字,作为标识符处理 识别数字 识别专用符号组合,如:=、<=、>= 识别特殊的单个字符,如+、-、/、* 跳过注释行(书中例子程序没有体现)
本课程采用第二种方法,Lex方法将在 后续时间补充介绍
2.词法分析程序的任务
词法分析程序的任务:对源程序进行扫描,提 供一个个符号给语法分析程序。 简称为扫描器(scanner)或扫描程序 词法分析程序实现的2种方案: 1.先单独工作一遍,把字符流源程序先变为符号 序列,输出到一个中间文件上,然后将这个文 件作为语法分析程序的输入继续第二遍的编译 过程

编译原理词法分析器-ll1-lr0-python实现代码

编译原理词法分析器-ll1-lr0-python实现代码

编译原理词法分析器-ll1-lr0-python实现代码计算机科学与通信工程学院编译原理实验报告题目: 1.词法分析器2. LL(1)分析器3. LR(0)分析器班级:姓名:学号:指导老师:2017年月目录一、实验题目 (1)二、实验目的和要求 (1)三、代码实现 (2)四、总结 (25)一、实验题目1.词法分析器分析一段程序代码,将代码中的单词符号分解出来,并对其进行检查,输出token表和error表2.LL(1)文法分析器分析给定文法。

求出文法的FIRST集,FOLLOW集,并构建分析表,对给定输入串进行分析。

3.LR(0)文法分析器分析给定文法。

用Ꜫ_CLOSURE方法构造文法的LR(0)项目集规范族,根据状态转换函数GO构造出文法的DFA,并转换为分析表,对给定输入串进行分析。

二、实验目的和要求1.学会词法分析器的实现思路。

2.学会求解FIRST集, FOLLOW集,构造LL(1)分析表。

3.学会Ꜫ_CLOSURE方法,状态转换函数GO, 构造LR(0)分析表。

三、代码实现1.词法分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i代码:KEYWORD_LIST = ['while', 'if', 'else', 'switch', 'case']SEPARATOR_LIST = [';', ':', ',', '(', ')', '[', ']', '{', '}']OPERATOR_LIST1 = ['+', '-', '*']OPERATOR_LIST2 = ['<=', '<', '==', '=', '>', '>=']CATEGORY_DICT = {# KEYWORD"while": {"while": ""},"if": {"if": ""},"else": {"else": ""},"switch": {"switch": ""},"case": {"case": ""},# OPERATOR"+": {"+": ""},"-": {"-": ""},"*": {"*": ""},"<=": {"relop": "LE"},"<": {"relop": "LT"},">=": {"relop": "GE"},">": {"relop": "GT"},"==": {"relop": "EQ"},"=": {"=": ""},# SEPARATOR";": {";": ""},":": {":": ""},",": {",": ""},"(": {"(": ""},")": {")": ""},"[": {"]": ""},"]": {"]": ""},"{": {"{": ""},"}": {"}": ""},}CONSTANTTABLE = []TOKENTABLE = []OPERATORTABLE = []KEYWORDTABLE = []SEPARATORTABLE = []UNDEFINEDTABLE = []# READ FILEdef read_file(path, method):temp_str = ""try:file = open(path, method)for line in file:line = line.replace('\n', " ") temp_str += linetemp_str = str(temp_str)except IOError as e:print(e)exit()finally:file.close()return temp_str.strip() + " "# GETBEdef getbe():global tokengetchar()token = ""return# GETCHARdef getchar():global characterglobal locationwhile all_string[location] == " ":location = location + 1character = all_string[location]return character# LINK TOKENdef concatenation():global tokenglobal charactertoken = token + character# IS NUMBERdef digit():if '0' <= character <= '9':return Truereturn False# IS ALPHABETdef letter():if 'A' <= character <= 'Z' or 'a' <= character <= 'z': return Truereturn False# IS IDENTIFIERdef reserve():if token in KEYWORD_LIST:return CATEGORY_DICT[token]else:return 0# RETRACTdef retract():global locationglobal character# location = location - 1character = ""return# MAIN FUNCTIONdef main():global tokenglobal characters = getchar()getbe()if 'a' <= s <= 'z' or 'A' <= s <= 'Z':while letter() or digit():concatenation()location = location + 1character = all_string[location]retract()c = reserve()if c == 0:TOKENTABLE.append(token)print("这是标识符:{'", token, "':'", TOKENTABLE.index(token), "'}") else:KEYWORDTABLE.append(token)print("这是保留字:", CATEGORY_DICT[token])elif '0' <= s <= '9':while digit():concatenation()location = location + 1character = all_string[location]retract()CONSTANTTABLE.append(token)print("这是常数:{'", token, "':'", CONSTANTTABLE.index(token), "'}") elif s in OPERATOR_LIST1:location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in OPERATOR_LIST2:location = location + 1character = all_string[location]if character == '=':OPERATORTABLE.append(s + character)print("这是双操作符:", CATEGORY_DICT[s + character])else:retract()location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in SEPARATOR_LIST:location = location + 1SEPARATORTABLE.append(s)print("这是分隔符:", CATEGORY_DICT[s])else:UNDEFINEDTABLE.append(s)print("error:undefined identity :'", s, "'")if __name__ == '__main__':character = ""token = ""all_string = read_file("program.txt", "r")location = 0while location + 1 < len(all_string):main()print('KEYWORDTABLE:', KEYWORDTABLE)print('TOKENTABLE:', TOKENTABLE)print('CONSTANTTABLE:', CONSTANTTABLE)print('OPERATORTABLE:', OPERATORTABLE)print('SEPARATORTABLE:', SEPARATORTABLE)运行结果:2.LL(1)分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i输入串:i+i*i代码:NonTermSet = set() # 非终结符集合TermSet = set() # 终结符集合First = {} # First集Follow = {} # Follow集GramaDict = {} # 处理过的产生式Code = [] # 读入的产生式AnalysisList = {} # 分析表StartSym = "" # 开始符号EndSym = '#' # 结束符号为“#“Epsilon = "~" # 由于没有epsilon符号用“~”代替# 构造First集def getFirst():global NonTermSet, TermSet, First, Follow, FirstAfor X in NonTermSet:First[X] = set() # 初始化非终结符First集为空for X in TermSet:First[X] = set(X) # 初始化终结符First集为自己Change = Truewhile Change: # 当First集没有更新则算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:k = 0Continue = Truewhile Continue and k < len(Y):if not First[Y[k]] - set(Epsilon) <= First[X]: # 没有一样的就添加,并且改变标志if Epsilon not in First[Y[k]] and Y[k] in NonTermSet and k > 0: # Y1到Yi候选式都有~存在Continue = Falseelse:First[X] |= First[Y[k]] - set(Epsilon)Change = Trueif Epsilon not in First[Y[k]]:Continue = Falsek += 1if Continue: # X->~或者Y1到Yk均有~产生式First[X] |= set(Epsilon)# FirstA[Y] |= set(Epsilon)# 构造Follow集def getFollow():global NonTermSet, TermSet, First, Follow, StartSymfor A in NonTermSet:Follow[A] = set()Follow[StartSym].add(EndSym) # 将结束符号加入Follow[开始符号]中Change = Truewhile Change: # 当Follow集没有更新算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:for i in range(len(Y)):if Y[i] in TermSet:continueFlag = Truefor j in range(i + 1, len(Y)): # continueif not First[Y[j]] - set(Epsilon) <= Follow[Y[i]]:Follow[Y[i]] |= First[Y[j]] - set(Epsilon) # 步骤2 FIRST(β)/~ 加入到FOLLOW(B)中。

哈工大编译原理.ppt

哈工大编译原理.ppt

procedure SORT(CH);
{ case CH of ‘字母’:
‘字母’: call RECOGID(CH,TOKEN);
‘/’: call HANDLECOM(CH,TOKEN);
‘数字’: call RECOGDIG(CH,TOKEN);
‘’‘
call RECOGSTR(CH,TOKEN);
if TOKEN!=‘ ’ then call PRINTERR(‘注解未完’);
TOKEN:=‘ ';
return }
25
识别界限符(RECOGDEL) 输入:CH内含单界限符; 输出:各种界符的TOKEN字; procedure RECOGDEL(CH,TOKEN); { case CH of
otherwise call RECOGDEL(CH,TOKEN);
end case;
write TOKEN into TOKEN文件;
Return } 23
procedure RECOGID(CH,TOKEN);
{ WORD:= ‘ ’; WORD:=WORD||CH; Repeat {
call GETCH(CH);
%%
标识符 {入口地址=LOOKUP();}
%%
LOOKUP()
31
辅助过程是动作需要的,这些过程用C书 写,可以分别编译.例:LOOKUP()
32
28
声明 %% 翻译规则 %% 辅助过程
29
声明包括变量,符号常量和正规定义式。
翻译规则的形式为:
p1
{ 动作1}
p2
{ 动作2}


pn
{ 动作n}
30
每个pi是正规定义式的名子,每个{动 作i}是正规定义式pi识别某类单词时,词 法分析器应执行动作的程序段。用C书 写。

编译原理课程设计报告——词法分析器

编译原理课程设计报告——词法分析器

精选课程设计任务书引言 (4)第一章概述 (5)1.1设计内容 (5)1.2设计要求 (5)第二章设计的基本原理 (6)2.1 (6)2.2 (6)第三章程序设计 (7)3.1 总体方案设计 (7)3.2 各模块设计 (8)第四章程序测试 (9)4.1一般测试4.2出错处理测试第五章结论 (10)参考文献 (10)附录程序清单 (11)引言《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机软件专业的一门重要专业课程。

该课程系统地向学生介绍编译程序的结构、工作流程及编译程序各组成部分的设计原理和实现技术。

由于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的软件设计算法,因此,一直是一门比较难学的课程。

为了使学生更好地理解和掌握编译技术的基本概念、基本原理和实现方法,实践环节非常重要,只有通过上机进行程序设计,才能使学生对比较抽象的教学内容产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对提高学生软件设计水平大有益处。

编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。

词法分析阶段是编译过程的第一个阶段,是编译的基础。

这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。

词法分析程序实现这个任务。

词法分析程序可以使用 Lex 等工具自动生成。

从左到右逐个字符对构成源程序的字符串进行扫描,依据词法规则,识别出一个一个的标记(token ),把源程序变为等价的标记串序列。

执行词法分析的程序称为词法分析器,也称为扫描器。

词法分析是所有分析优化的基础,涉及的知识较少,如状态转换图等,易于实现。

本次课程设计,我的选题是词法分析, C++ 代码实现。

第一章概述1.1 设计内容对 C 语言的一个子集设计并实现一个简单的词法分析器,掌握利用状态转换图设计词法分析器的基本方法。

1.2设计要求利用该词法分析器完成对源程序字符串的词法分析。

编译原理第一次上机(词法分析器)

《词法分析器的构造》综合性实验大纲一、实验目的设计、编制、调试一个词法分析程序,对单词进行识别和编码,加深对词法分析原理的理解。

二、设计内容设计并实现一个词法分析器,实现对指定位置的类C语言源程序文本文件的读取,并能够对该源程序中的所有单词进行分类,指出其所属类型,实现简单的词法分析操作。

例如下面为一段C语言源程序:main(){int a,b;a = 10;b = a + 20;}要求输出如下(可以自行分类,分类原则请在报告中说明)(1,’main’)(5,’(’)(5,’)’)(5,’{ ’)(1,’int’)(2,’a’)(5,’,’)(2,’b’)(5,’;’)(2,’a’)(4,’=’)(3,’10’)(5,’;’)(2,’b’)(4,’=’)(2,’a’)(4,’+’)(3,’20’)(5,’;’)(5,’}’)三、实验要求1、允许用户自己输入源程序并保存为文件2、系统能够输出经过预处理后的源程序(去掉注释、换行、空格等)3、能够将该源程序中所有的单词根据其所属类型(整数、保留字、运算符、标识符等。

定义的类C语言中的标识符只能以字母或下划线开头)进行归类显示,例如:识别保留字:if、int、for、while、do、return、break、continue等,其他的都识别为标识符;常数为无符号整形数;运算符包括:+、-、*、/、=、>、<、>=、<=、!=等;分隔符包括:,、;、{、}、(、)等。

4、实现文件的读取操作,而不是将文本以字符串形式预存于程序中。

文本内容为待分析的类C语言程序。

四、实验报告实验报告的内容:实验名称、实验目的、实验任务、实验内容、实验过程描述(包括实验结果分析、实验过程遇到的问题及体会)。

实验报告的要求:实验报告以文本或电子版形式递交,实验报告书写要求如下:1. 问题描述:包括实验名称、目的、内容(包括所识别的单词文法),以简洁明了的叙述说明本次上机实验的任务和目标,程序的输入和输出要求以及程序的功能。

编译原理NFA

编译原理NFANFA(Non-deterministic Finite Automaton,非确定有限自动机)是一种用于描述正则语言的有限状态自动机。

NFA可以由以下元素构成:一组状态,一个输入字母表,一个状态转移函数和一个初始状态及一组接受状态。

在编译原理中,NFA常常用于构建正则表达式的匹配器或者词法分析器。

下面是一个简单的NFA的定义和构造过程:1. NFA的定义:-状态集合:一组状态,每个状态用一个唯一的标识符表示。

-输入字母表:包含所有可能的输入符号。

-状态转移函数:描述状态之间的转移关系,它是一个映射函数,将一个状态和一个输入符号映射到一组可能的下一个状态。

对于NFA来说,一个状态和一个输入符号可能对应多个下一个状态,这是与确定有限自动机(DFA)的主要区别之一。

-初始状态:NFA的起始状态。

-接受状态:一组接受状态,表示匹配成功的状态。

2. 构造NFA:-对于每个正则表达式的元素(字符或操作符),构造相应的NFA片段。

-对于字符元素,构造一个简单的NFA片段,包含两个状态和一个输入转移。

-对于连接操作符(.),将两个NFA片段连接起来,即将第一个NFA片段的接受状态指向第二个NFA片段的初始状态。

-对于选择操作符(|),构造两个NFA片段,然后添加一个新的初始状态和两个ε(空)转移,将新的初始状态指向这两个NFA片段的初始状态,并将两个NFA片段的接受状态指向一个新的接受状态。

-对于闭包操作符(*),构造一个NFA片段,添加一个新的初始状态和两个ε转移,将新的初始状态指向原NFA片段的初始状态,并将原NFA片段的接受状态指向新的接受状态。

然后添加两个ε转移,将新的初始状态和新的接受状态连接起来。

通过这样的方式,可以逐步构建出完整的NFA,最终得到一个能够接受特定正则表达式定义的语言的NFA。

需要注意的是,NFA在状态转移时可以有多个选择,这种非确定性使得NFA在实际匹配过程中可能需要进行回溯。

编译原理课程设计-LL(1)语法分析器的构造

LL(1)语法分析器的构造摘要语法分析的主要任务是接收词法分析程序识别出来的单词符由某种号串,判断它们是否语言的文法产生,即判断被识别的符号串是否为某语法部分。

一般语法分析常用自顶向下方法中的LL分析法,采用种方法时,语法分程序将按自左向右的顺序扫描输入的的符号串,并在此过程中产生一个句子的最左推导,即LL是指自左向右扫描,自左向右分析和匹配输入串。

经过分析,我们使用VC++作为前端开发工具,在分析语法成分时比较方便直观,更便于操作。

运行程序的同时不断修正改进程序,直至的到最优源程序。

关键字语法分析文法自顶向下分析 LL(1)分析最左推导AbstractGrammatical analysis of the main tasks was to receive lexical analysis procedure to identify the words from a website, string, and judge whether they have a grammar of the language, that is, judging by the series of symbols to identify whether a grammar part. General syntax analysis commonly used top-down methods of LL analysis, using methods, Grammar hours will be from the procedures of the order left-to-right scanning input string of symbols, and in the process produced one of the most left the sentence is derived, LL is scanned from left to right, From left to right analysis and matching input strings. After analysis, we use VC + + as a front-end development tool for the analysis of syntax ingredients more convenient visual, more easy to operate. Operational procedures at the same time constantly improving procedures, until the source of optimal .Key WordsGrammatical analysis grammar Top-down analysis LL (1) AnalysisMost left Derivation目录摘要 (1)引言 (3)第一章设计目的 (4)第二章设计的内容和要求 (5)2.1 设计内容 (5)2.2 设计要求 (5)2.3 设计实现的功能 (5)第三章设计任务的组织和分工 (6)3.1 小组的任务分工 (6)3.2 本人主要工作 (6)第四章系统设计 (9)4.1 总体设计 (9)4.2 详细设计 (9)第五章运行与测试结果 (22)5.1 一组测试数据 (22)5.2 界面实现情况 (23)第六章结论 (27)课程设计心得 (28)参考文献 (29)致谢 (30)附录(核心代码清单) (31)引言编译器的构造工具是根据用户输入的语言的文法,编译器的构造工具可以生成程序来处理以用户输入的文法书写的文本。

编译原理 第五章 词法分析


三、LEX编译程序的工作过程:
1.根据每条识别规则Pi {ACTION i}构造相应的非确 定有限自动机NFA,分别画出它们的状态转换图; 2.将所有的状态转换图连接成一个完整的状态转换图; 3.由状态转换图构造状态转换矩阵; 4.将状态转换矩阵确定化; 5.根据DFA,构造词法分析器;
预处理 子程序 扫描器 单词符号
输入 列表 输入缓冲区
扫描缓冲区
词法分析器的结构
三、设置缓冲器的必要性
之所以要设置缓冲器,是因为对于许多源程序而言,有 时词法分析器为了得到某个单词符号的确切性质,只从该符 号本身所含有的字符不能作出判定,还需要超前扫描若干字 符之后,才能作出确切的分析。 例如:有合法的Fortran语句: DO99K=1,10 和 DO99K=1.10 前者是循环语句,后者是赋值语句,两者的区别在于等 号后的第一个界符不同,前者是逗号,后者是句号,因此为 了识别前者中的关键字‘“DO”,必须超前扫描若干字符之 后,才能作出确切的判定。
3、词法分析器和语法分析器作为协同程序 如果两个或两个以上的程序,他们之间交叉执行,这些程序称为协同程 序。词法分析器和语法分析器也可协工作的方式安排在同一遍中,以生产 者和消费者的关系同步运行。
1.词法分析单独作为一遍
S.P.(字符串)
第一 遍 词法分析 单词 串 S.P.(符号串) 第二 遍 语法分析
例如:
%{ int wordCount = 0; int noCount = 0; %} chars [A-za-z] numbers ([0-9])+ words {chars}+ 注意:凡是对已经定义的正则表达式的名字的引用,都必须用花括 号将它们括起来。在LEX源程序中,起标识作用的符号%%,%{以及%}都 必须处在所在行的最左字符位置。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
四、实验小结(包括问题和解决方法、心得体会、意见
与建议等)
这次实验让我们更加了解词法分析程序的原 理,熟悉了书上词法分析程序构建的步骤,也强 化了我们的编程能力,比如说文件读写操作。在 我的程序中,思考了很久也没能实 现”<=””>=”和”!=”的词法分析。拿”>=”举例来 说,CHAR读了”>”之后,进行判断如果是”=”就 输出“(4,’>=’)”。但是如果接下来的字符不 是”=”,就需要判断这个CHAE字符是否为字母、 数字、分隔符、其他运算符,这样就会和之前的 判断进入一个死循环(因为在保留字判断的时候 也要多读一个字符,判断为否定后要比较这个字 符是否为数字,分隔符,运算符)。总的来说就 是我不能将文件指针前移,导致这里写不出来,
} bool REAERVE(char *a) {
//判断标识符是否为保留字
if(strcmp(a,"if")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"int")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"for")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"while")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"do")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"return")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"break")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"continue")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"main")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} return false; }
return true; else return false; } bool DIGIT (char A) { if(A>='0'&&A<='9')
return true; else
return false; } bool REAERVE(char *a) {
if(strcmp(a,"if")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"int")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"for")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"while")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"do")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"return")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"break")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"continue")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} if(strcmp(a,"main")==0) {cout<<"(1,'"<<a<<"')"<<endl;return true;} return false; } bool zimu(char A) {
实验报告
(2014 / 2015 学年 第 一 学期)
课程名 称
实验名 称
实验时 间
指导单 位
指导教 师
编译原理 词法分析器的构造
2015 年 4 月 10 日 南京邮电大学 蒋凌云
学生姓名 孙雪禄
学院(系) 计算机学 院、软件 学院
班级学 号
专业
B12041213
软件工程 (服务外
包)
实验名 称
TOKEN[i]='\0';
if(!REAERVE(TOKEN))
cout<<"(3,'"<<TOKEN<<"')"<<endl;
}
if(CHAR=='+'||CHAR=='-
'||CHAR=='*'||CHAR=='/'||CHAR=='>'||CHAR=='<'||CHAR=='=') //运?算?符?
else if(A>='A'&&A<='Z') return true;
else return false; } bool DIGIT (char A)
//判断字符是否是字母 //判断字符是否是数字
{ if(A>='0'&&A<='9') return true; else return false;
while((CHAR=fgetc(f))!=EOF)
{
while(CHAR!=' ')
{
if(zimu(CHAR))
//标括?识?符?
{
int k=0;
do{
TOKEN[k]=CHAR;
k++;
}while((CHAR=fgetc(f))!=EOF&&CHAR!=' '&&zimu(CHAR));
(1)首先讲和书上一样分成5类
分类号 分类内容
1
保留字
2
标识符
3
整数
4
运算符(+,-,*,/,>,<,=等)
5
分隔符(,,;,{,},(,))
(2)、接着写出用到的简单文法并转换成状态转换图
<标识符>::=字母|字母<标识符>|<标识符>数字
<整数>::=数字|数字<整数>
<运算符>::=+|-|*|<|>|=
cin>>CHAR;
return 0; }
测试结果:
文件存储在code.txt文件中
0 ⑤ ⑥ 3 1 ② ④ 字母 非数字或字母 字母或数字 数字 数字 非数字 +-*/=>< ,;( ){} 0 ⑤ ⑥ 3 1 ② ④ 字母
非数字或字母 字母或数字 数字 数字 非数字 +-*/=>< ,;( ){}
<分隔符>::=,|;|(|)|{|}
保留字是一种特殊的标识符,不独立写出其文法
状态转换图如下:
(3) 按照书上的步骤写程序
相关文档
最新文档