编译原理之正则表达式转NFA

前言:继上次的《自己写一个简单的C++单词扫描程序》之后,编译原理实验课要求做一个Regural Express 转NFA
图,这个在算法上没什么难度,在《编译原理与实践》书上介绍了Thompson的转换算法,该书对Thompson
算法做了详细的文字描叙,如想对该算法更深的了解参照:机械工业出版社,《编译原理与实践》译本P.45。
正文:
一、问题分析:
 要求输入一个正则表达式,将其转换为NFA,并输出结果。转化的方法有多种,应用Thompson结
构的转换方法最为简单。Thompson结构:它利用epsilon—转换将正则表达式的机器片段“粘贴在一起”
以构成整个表达式相应的机器。它依照了正则表达式定义的结构:为每个基本正则表达式展示一个NFA,
接着通过连接子的运算将每个正则表达式运算,连接起来。正则表达式的运算有四种:连接,选择,闭包
,正闭包(本程序不支持该运算)。
二、系统设计:
总体设计:为了提高程序的可移植性,将其分为界面类,NFA图类,NFA_Node(NFA图结点)类,Converte
r(转换器)类以及一个Transition(状态传输)结构体。
程序设计:选用C++Builder6.0(BCB6)作为开发工具。转换的运算类似普通的四则运算,Union的运算符
为“|”,Closure的运算符为“*”,而在表达式中的Connect连接运算表示为两个字符的连接 eg:ab,
则需要引入一个符号来区分是否为连接运算,在此引入“&”为连接符号,即上例变为a&b,为此便于编程
。三种运算的优先级从高到低依次为:*、&、| ,而运算的方法完全按照Thompson结构的算法,所以在此
不再螯述。参照普通的四则运算,在正则表达式的转换运算中,引入两个栈,一个为运算符栈,另一个为
运算数栈,而这里的运算数为局部的NFA图。栈的设计应用类模板,减少了没必要的重复代码,提高设计
的抽象程度。
三、部分程序源码:(为了省出切换输入法的时间,主要算法的注释用了英文描述,鉴于本人英文较差,
主要是写给自己看的,如果您看不懂注释,请见谅。)
/*以下为界面的事件触发部分*/
/*对输入字符串做预处理,插入“&”和“=”*/
AnsiString __fastcall TForm1::preTreatStr(AnsiString InRegEx)
{
  int i = 1;
  char ch,prech;
  InRegEx = InRegEx + '=';
  prech = InRegEx[i++];
  ch = InRegEx[i];
  while(InRegEx[i]!='=')
  {
     if((isalpha(prech)&&isalpha(ch)) || (isalpha(prech)&&ch=='(') || 
(prech==')'&&isalpha(ch)) || (prech=='*'&&isalpha(ch)) || (prech=='*'&&ch=='('))
     {
       InRegEx.Insert('&',i);
     }
     prech = InRegEx[i++];
     ch = InRegEx[i];
  }
  return InRegEx;
}
/*遍历出NFA图*/
void __fastcall TForm1::Display(NFA Grap)
{
       Memo1->Lines->Add("转换为NFA的结果为:");
       Grap.Ncurrent = Grap.Nstart;       //set current = start and begin scan
       Memo1->Lines->Add(IntToStr(Grap.Ncurrent->stateID)+"开始状态");
       while(Grap.Ncurrent->Nnext!=NULL)
       {
          if(Grap.Ncurrent->Thead->Tnext!=NULL) //while have transmit
          {
            Grap.Ncurrent->Tcurrent = Grap.Ncurrent->Thead->Tnext;
            while(Grap.Ncurrent->Tcurrent->Tnext!=NULL)
            {
              if(Grap.Ncurrent->Tcurrent->incept!='@')
              {
Memo1->Lines->Add(IntToStr(Grap.Ncurrent->stateID)+"--->"+IntToStr(Grap.Ncurrent->Tcurrent->
State)+"接收到:"+Grap.Ncurrent->Tcurrent->incept);
              }
              else
              {
Memo1->Lines->Add(IntToStr(Grap.Ncurrent->stateID)+"--->"+IntToStr(Grap.Ncurrent->Tcurrent->
State)+"接收到:epsilon");
              }
               Grap.Ncurrent->Tcurrent = Grap.Ncurrent->Tcurrent->Tnext;
            }
            if(Grap.Ncurr
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值