词法分析怎么用折半查找的时间复杂度保留字

3.1 词法分析程序
&&&&词法分析是翻译的第一阶段,是语法分析的必要准备。词法分析程序也称为扫描程序或扫描器(scanner)。
&&&&词法分析是编译过程中的一个阶段,可以在语法分析前进行 。也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
1.实现方法
&&①作为单独的一遍
&&字符序列 &&&&单词序列 
───&扫描器───&语法分析器──& . .
&&②作为子程序
2.词法分析程序的主要任务
&&&&读源程序,产生单词符号
&&&&词法分析程序的其他任务:
&&&&- 滤掉空格,跳过注释、换行符
&&&&- 追踪换行标志,复制出错源程序,
&&&&- 宏展开

3.词法分析程序的输出
单词可作各种分类,典型地分为5类:
AND,BEGIN,FOR,TYPE,VAR等
②标识符 用户定义的常量、类型、变量、过程名
③常量 12, 1997,
4.14, ‘A’, 等
④运算符 +,-,*,/,&,&&,!=,#等
⑤界限符 ; , ( ) 等
词法分析程序所输出的单词符号常常采用以下二元式表示:
(单词种别,单词自身的值)。
单词的种别是语法分析需要的信息,而单词自身的值则是编译其它阶段需要的信息。
比如在PASCAL的语句const i=25, yes=1;中的单词 25和1的种别都是常数,常数的值25和1对于代码生成来说,是必不可少的。
有时,对某些单词来说,不仅仅需要它的值,还需要其它一些信息以便编译的进行。
比如,对于标识符来说,还需要记载它的类别、层次还有其它属性,如果这些属性统统收集在符号表中,那么可以将单词的二元式表示设计成如下形式
(标识符,指向该标识符所在符号表中位置的指针)
如上述语句中的单词i和yes的表示为:
(标识符,指向i的表项的指针)
(标识符,指向yes的表项的指针)
单词的种别可以用整数编码表示,假如
&&&&标识符编码为&&&&&&1
&&&&常数为&&&&&&&&&&&&2
&&&&保留字为&&&&&&&&&&3
&&&&运算符为&&&&&&&&&&4
&&&&界符为&&&&&&&&&&&&5
程序段 if i=5 then x∶=y;在经词法分析器扫描后输出的单词符号和它们的表示如下:
 - 保留字if(3,'if')
 - 标识符i(1,指向i的符号表入口)
 - 等号=(4,'=')
 - 常数5(2,'5')
 - 保留字then(3,'then')
 - 标识符x(1,指向x的符号表入口)
 - 赋值号∶=(4,'∶=')
 - 标识符 y(1,指向y的符号表入口)
 - 分号;(5,';')  
4.词法分析在实际操作中
对于每种语言,保留字、运算符和界限符是固定的,可以“一字一类”或“一符一类”,预先造好标准单词表。
常数虽然也是固定的,但个数太多,而每个程序只用很少一部分,不宜预先造表。编译只对源程序中出现的各类常量造表,如整数表、实数表、字符串表等。
例如:整数表IntTab存放源程序中的整常数,扫描器拼出整数时,查IntTab表,若无此数,则填入表中;若已有此数,则不在填入,而把该数在表中的地址intp作为其机内码的一部分,由它联系机内码和数值。
标识符的意义是由用户定义的,与常量类似,编译器也构造一个标识符表IdTab。每识别出一个标识符,则查IdTab表,若无则填入,已有则不填,用其在表中的地址idp作为联系机内码和自身值的桥梁。
词法分析工作从语法分析工作独立出来的原因:(P48)
&&&简化设计
&&&改进编译效率
&&&增加编译系统的可移植性
5.PL/0词法分析的设计与实现
`PL/0的词法分析程序GETSYM(P15图2.5)是一个独立的过程,其功能是为语法分析提供单词用的,是语法分析的基础,它把输入的字符串形式的源程序分割成一个个单词符号。为此PL/0编译程序设置了三个全程量的公用单元如下:
SYM:存放每个单词的类别,用内部编码形式表示
ID: 存放用户所定义的标识符的值。
NUM:存放用户定义的数。
单词的种类有五种。
基本字:也可称为保留字或关键字,如BEGIN,END,IF,THEN等。
运算符:如:+、-、*、/、∶=、#、>=、<=等。
标识符:用户定义的变量名、常数名、过程名。
常数:如:10,25,100等整数。
界符:如:','、'.'、';'、'('、')'等。
PL/0编译程序文本中主程序开始对关键字表置初值如下(P304 ) :
关键字表为:
word[1]:='begin ';word[2]:='call ';
word[13]:='write ';
查到时找到关键字相应的内部表示为:
Wsym[1]:=wsym[2]:=callsym;
wsym[13]:=writesym;
因此词法分析程序GETSYM将完成下列任务(1) 滤空格:空格在词法分析时是一种不可缺少的界符,而在语法分析时则是无用的,所以必须滤掉。
(2) 识别保留字:设有一张保留字表。对每个字母打头后接字母或数字的字符串要查此表。若查着则为保留字,将对应的类别放在SYM中。如IF对应值IFSYM,THEN对应值为THENSYM。若查不着,则认为是用户定义的标识符
(3)识别标识符:对用户定义的标识符将IDENT放在SYM中,标识符本身的值放在ID中。
(4) 拼数:当所取单词是数字时,将数的类别NUMBER放在SYM中,数值本身的值存放在NUM中。
注意:SYM是纯量/枚举类型
symbol=(nul,ident,number,plus,…,varsym,procsym)
(5) 拼复合词:对两个字符组成的算符
如:>=、∶=、<=
等单词,识别后将类别送SYM中。
(6) 输出源程序:为边读入字符边输出(可输出在文件中)。PL/0的词法分析程序(见P290-292页)编译原理第三章 词法分析编译,词法分析,编译原理,第三章,编译原理第,词法分析器
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
编译原理第三章 词法分析
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口编译原理 词法分析编译原理
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
编译原理 词法分析
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口C0编译器C0Compiler——词法分析部分
自个儿编的时候有点费劲,多亏有童鞋愿意共享资料,所以偶也来贡献一下下。。。偶这个不是很好用,大神可以直接忽略,不过对于不咋会编的童鞋还是能参考一下滴。。。
Analyse_word.c
#include&string.h&
#include "C0Compiler.h"
*resWord[reservednum]={{"case"},{"char"},{"const"},{"default"},{"else"},{"float"},{"for"},{"if"},{"int"},{"main"},{"printf"},{"return"},{"scanf"},{"switch"},{"void"},{"while"}};
intindex=0;
errorflag=0;
void getsym()
&int k=0,i,j;
&//过滤读取一个单词前的所有空白符
&while( ch==' ' || ch=='\n' || ch=='\t' ||
ch=='\0' )
&&getch();
&//当前读取的字符是字母,那么下面要读入的单词是标识符或关键字
&if (isLetter(ch))
&&while (isLetter(ch) ||
isDigit(ch)) {
&&&id[k++] =
//id数组保存标识符的值
&&&getch();
&&id[k]='\0';
&&//折半查找,因为关键字是按字典序排列的
&&j = reservednum-1;
&&while (i&=j)
(strcmp(id,resWord[k])==0)
(strcmp(id,resWord[k])&0) j = k-1;
(strcmp(id,resWord[k])&0) i = k+1;
&&//是关键字,则以数组下标去对应枚举常量的值
&&if (i&=j) sym =
(symkind)k;
&&//只是普通标识符
&&else sym =
&//当前读入的字符是数字
&if (isDigit(ch))
&&char ch_next,temp =
&&intnum = realnum = 0;
&&getch();
&&ch_next =
&&//读到的单词是0的情况
&&if (ch=='0'
&& ch_next!='.') {
&&&intnum =
//读到的数为0
&&&intnumstr[intindex++]
&&&codec--;
&&&//先读取整数部分,但还不确定是否为整数
&&&codec--;
(isDigit(ch)) {
&&&&intnumstr[intindex++]
&&&&intnum
= intnum*10 + (ch-'0');
&&&&getch();
&&&//出现.则是浮点数
(ch=='.')&{
real_temp=1;
&&&&intnumstr[intindex++]
&&&&realnum
&&&&intnum
&&&&getch();
&&&&//读取小数部分
(isDigit(ch)){
&&&&&intnumstr[intindex++]
&&&&&real_temp
&&&&&realnum
+= real_temp*(ch-'0');
&&&&&getch();
&&&&intnumstr[intindex]
'\0';&&&&&
//将读到的数字符号串以'\0'结尾
&&&&intindex
&&&//未出现.则是整数
&&&&codec--;
&&intnumstr[intindex] =
'\0';&&&&&
//将读到的数字符号串以'\0'结尾
&&intindex = 0;
&&getch();
&//当前读入的单词是'&'和'&='的情况
&if(ch=='&')
&&getch();
&&if (ch=='=') {
&&&getch();
&&else&&&&
&//'&'和'&='
&if(ch=='&')
&&getch();
&&if (ch=='=' ) {
&&&getch();
&//'=='和'='
if(ch=='=')&&&&&&&&
&&getch();
&&if (ch=='=' ) {
&&&getch();
&if(ch=='!')&&&&&
&&getch();
&&if(ch=='=' ) {
&&&getch();
&&&error(0);
&//<字符>&&&
::=& '<加法运算符>|<乘法运算符>|<字母>|<数字>'
&if(ch=='\'')
&&getch();
&&if (ch=='+' || ch=='-' ||
ch=='*' || ch=='/' || isLetter(ch) || isDigit(ch) ) {
&&&if (ch=='\'')
&&&&intnumstr[intindex++]
&&&&intnumstr[intindex]
&&&&intindex
&&getch();
&&error(0);
&&intindex = 0;
&//出现“时,将双引号之间的字符串全部读入str[]中
&if(ch=='"')
&&getch();
&&while (ch!='"') {
&&&str[i++] =
&&&if (ch=='\\')
&&&&getch();
&&&&if(ch=='n')
&&&&&str[i-1]='\n';
if(ch=='t')
&&&&&str[i-1]='\t';
if(ch=='b')
&&&&&str[i-1]='\b';
if(ch=='\'')
str[i-1]='\'';
if(ch=='"')
&&&&&str[i-1]='"';
&&&&&str[i-1]=
&&&getch();
&&str[i] = '\0';
&&getch();
&switch(ch) {
&&&getch();
&&case '-':
&&&getch();
&&case '*':
&&&getch();
&&case '/':
&&&getch();
&&case '(':
&&&getch();
&&case ')':
&&&getch();
&&case '{':
&&&getch();
&&case '}':
&&&getch();
&&case ',':
&&&getch();
&&case ';':
&&&getch();
&&case EOF:
&&&sym=EOF
&&case ':':
&&&getch();
&&default:
&&&error(0);
&&&getch();
int isLetter(char ch) {
(ch&='a'&&ch&='z')
(ch&='A'&&ch&='Z')
) return 1;
&return 0;
int isDigit(char ch) {
(ch&='0'&&ch&='9')
) return 1;
&return 0;
void exchange(char name[])
&while(name[i]!='\0') {
&&if(name[i]&='A'&&name[i]&='Z')
&&&name[i]+=32;
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 折半查找平均查找长度 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信