编译原理实验 之 词法分析


     词法分析步骤是编译器处理的第一步,目的是将用户输入的符号流转化为 后面语法分析所需的 词法单元的形式.

    

    一般来说,经过了词法分析之后, 所有的输入内容都将变成"编译器可识别"的形式. 词法单元主要分为几类, 比如标示符,常量,标点符号,操作符,关键字等等. 对于常量和标示符而言,词法分析的结果还应该包含它所带有的实际含义和值.

 

    词法分析的作用: 1.剔除空格 换行符 制表符等等,

    2.通过换行符记录数据的行数,以便在返回错误的时候定位到错误行.

    

   词法分析的实现有很多方式,这里我们采用栈的数据结构对其词法分析过程进行模拟.


    先贴出我们实验课的词法内容吧.
  
    
(1)待分析的简单语言的词法
1) 关键字
begin if then while do end
2) 运算符和界符
:= + - * / < <= > >= <> = ; ( ) #
3) 其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
4) 空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。

4) 空格由空白、制表符和换行符组成。空格一般用来分隔IDNUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2)各种单词符号对应的种别编码

单词符号

种别码

单词符号

种别码

begin

1

:

17

if

2

:=

18

then

3

<

20

while

4

<>

21

do

5

<=

22

end

6

>

23

letter(letter|digit)*

10

>=

24

digitdigit*

11

=

25

+

13

;

26

-

14

(

27

*

15

)

28

/

16

#

0

3)词法分析程序的功能

输入:所给文法的源程序字符串

输出:二元组(syn, tokensum)构成的序列。

syn为单词种别码;

token为存放的单词自身字符串;

sum为整形常数。

例如:对源程序begin x:=9;if x>0 then x:=2*x+1/3;end# 经词法分析后输出如下序列:(1begin(10,’x’) (18,:=) (11,9) (26,;) (2,if)……





   实验的内容并不复杂,用到的数据结构和类型也很简单,没有什么复杂的算法,慢慢写就可以了.


   后面就是代码了,也许会有些小bug,因为后面改的时候不记得是否保存了.....不过应该不是大问题..大家参考就好.
   
   
#include "define.h"




int _isLetter(char exp)                        //判断字母
{
    
if(exp >='A'&&exp<='Z'||exp>='a'&&exp<='z')
return 1;
return 0;
};




bool _isKey(string s)                                   //判断关键字
{
if(Keylist->Key_search(s))
  return true;
return false;
};


bool _isOpe(char c)                             //判断操作符
{
if(Opelist->Ope_search(c))
return true;
return false;
};


int _isDigit(char exp)                          //判断数字
{
if(exp >='0'&&exp <='9')
return 1;
return 0;
};




int NO(char c)                               //返回键值
{
if(c=='+')return 13;
if(c=='-')return 14;
if(c=='*')return 15;
if(c=='/')return 16;
if(c=='>')return 20;
if(c=='<')return 23;
if(c=='=')return 25;
if(c==':')return 17;
if(c==';')return 26;
if(c=='#')return 0;
if(c==')')return 28;
if(c=='(')return 27;
};
int NO(char c1,char c2)
{
if(c1=='<'&&c2=='>')return 21;
if(c1==':'&&c2=='=')return 18;
if(c1=='<'&&c2=='=')return 22;
if(c1=='>'&&c2=='=')return 24;
};




void print()                                       //打印函数,也是处理栈,
{
int sz;
int n[MAX_LENGTH];char str[MAX_LENGTH] ={' '};char o[MAX_LENGTH] = {' '};
if(!cs.empty())
{
   sz = cs.size();
for(int i=sz-1;i>-1;i--)
{ str[i]=cs.top();cs.pop();}
if(_isKey(str));
else {cout<<"("<<10<<",";
        for(int j=0;j<sz;j++)
cout<<str[j];cout<<")"<<endl;}
}
else if(!ns.empty())
{
sz = ns.size();
for(int i=sz-1;i>-1;i--)
{
            n[i]=ns.top();
       ns.pop();
        }
        cout<<"("<<11<<",";
for(int j=0;j<sz;j++)
cout<<n[j]-48;
cout<<")"<<endl;
}


};


ostream& operator << (ostream& out,char*  st)
{
int i=0; 
while(i<sizeof(st))
{out<<st[i];i++;}
return out;
};




void analysis(const char* filename)                    //词法分析的主体,遇到其他符号的时候就跳到栈的处理,完成匹配.
{
   filein.open(filename,ios::in);
   if(!filein)
   {
  cout<<"File open error!\n";
  return ;
   }
   char c;
   while((c = filein.get())!=EOF)
   {
      
       if(_isOpe(c))
  {
  if(!os.empty())
  {
  cout<<"("<<NO(os.top(),c)<<";"<<os.top()<<c<<")"<<endl;
  os.pop();
  }
  else os.push(c);
  print();                                 //跳
  }
       if(_isLetter(c)==1)
  {   
  cs.push(c);
      if(!os.empty())
  {
  cout<<"("<<NO(os.top())<<";"<<os.top()<<")"<<endl;
  os.pop();
  }
  }
  else if(_isDigit(c)==1&&!cs.empty())
  {
  cs.push(c);
  if(!os.empty())
  {
  cout<<"("<<NO(os.top())<<";"<<os.top()<<")"<<endl;
  os.pop();
  }
  }
  else if(_isDigit(c)==1)
  {   
  ns.push(c);
           if(!os.empty())
  {
  cout<<"("<<NO(os.top())<<";"<<os.top()<<")"<<endl;
  os.pop();
  }     
  }
  else if(c=='\t'||c==' '||c=='\n')
  {   
  if(!os.empty())
  {
  cout<<"("<<NO(os.top())<<";"<<os.top()<<")"<<endl;
  os.pop();
  }  
  print();                       //跳
  }
   }
   filein.close();
};
      上面就是词法分析的核心部分了.也不是很难,细节部分的处理注意一下就好了.
 
       本系列博客的目的其实就是让后面需要的人有个例子对比而已,有发现bug的可以提出来.
      
       最后如果有需要全部代码的可以私信我,在线必回~~
    
      下一次就是自顶向下的语法分析程序了,期待吧~
此资源包含源代码和实验报告。 一、实验目的 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。 二、实验要求 该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、数据、运算符、分界符等五大类,并依次输出各个单词的种类及单词符号自身值。若遇到错误则显示“Error”,然后跳过错误部分继续显示 。 三、实验内容 通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示。 以下是实现词法分析设计的主要工作: (1)从源程序文件中读入字符。 (2)删除空格类字符,包括回车、制表符空格。 (3)按拼写单词,并用(单词,属性)二元式表示。 (4)如果发现错误则报告出错。 单词的基本分类: 关键字:由程序语言定义的具有固定意义的标识符。也称为保留字例如 i f、const; 单词种别码为1。 标识符:用以表示各种名字,如变量名、数组名、函数名;种别码为2。 数据: 任何数值常数。如 125,3.14等;种别码为3。 运算符:+、-、*、/、<、、>=、;种别码为4。 分界符: ; 、, 、(、) 、[、];种别码为5。 Error:#、%等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值