[cp] 词法分析器的自动生成

本文围绕自动机展开,先介绍输入规则,将输入按特定结构存储,正规定义式和识别规则分别用不同的vector结构保存,该过程在Read函数实现。接着阐述把输入转换为自动机,先根据正规定义式生成自动机,再基于此根据识别规则生成不确定自动机,最后合并分散自动机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 我的目标只是按照课本上所说的,一个表格,一个控制程序,而控制程序大部分没什么变化,只是根据识别动作做相应的一点改变而

已,最后虽然完成了,但不能肯定它的正确性,还好多次测试都没什么问题……(简单的测试)HOHO

 自动机在程序中的存储结构,我会在另外一篇待写的文章中说明,这里,我是考虑如何根据下面的输入来生成一个最终的自动机,并

产生一个对应识别动作的分析程序……

首先说明一下输入规则:
  在单引号之间的字符属于自动机的字符表,即单引号作用类似于转义字符
  在尖括号里的值对应的字符属于自动机的字符表 即:
 digit->'*' 表示自动机的字符表中包含 *  号,一般该符号用于表示闭包。
 any-><10>  表示自动机的字符表中包含换行符(好像换行符号的值是 10 吧 )

// [下面是输入 首先是正规定义式 >LIBRARY 然后是识别规则 >RECGNITION]
>LIBRARY
 digit->1234567890
 letter->abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
 id->letter(letter|digit)*
>RECGNITION
 if  {return 0;/*enum if = 0*/}
 id  {return 1;/*enum id = 1*/}

首先把输入按照一定结构存储,用一个vector<string> m_library_names 保存所有的正规定义式的名字,比如digit,letter等,而每个定义的

右边则用一个vector<pair<bool,void*/*any*/> > 结构保存,其中每个pair 保存的信息是:(bool )false表示存放原始数据,true表示存放

着该定义式之前存在的正规定义式的位置,


例如:
 上面的 id->letter(letter|digit)* 最终保存的结果是:
m_library_cores[2 /*2表示该定义的位置*/ ] = { (true,1),(false,"("),(true,1),(false,"|"),(true,0),(false,")*") }
其他的正规定义式都按照如此结构保存。这样,所有的定义式保存在一个vector<vector<pair<bool,void*/*any*/> > >m_library_cores中

 然后是识别规则的存储,规则的左边存储形式与正规定义式的右边存储格式一样,用一个vector<pair<bool,void*/*any*/> > 的结构

保存每个识别规则的左边,左边部分均保存在vector<vector<pair<bool,void*/*any*/> > > m_recginitions 中,右边是相应的识别动作,用

vector<string>保存,注意这里保存的顺序与输入的顺序一致,方便以后自动机识别后能找到对应的动作。

输入部分的存储便完成,该过程在 函数 Read 中实现

/*
 * [如果是正确的输入则返回 true 否则false]
 **/
bool Read(istream& input_stream);


接着是把输入转换为自动机.

首先根据正规定义式生成自动机,代码大致如此:

 // [把各个正规定义式生成的确定自动机放到 m_dfaList 中]
 for(unsigned int  i=0; i<this->m_library_cores.size(); i++ )
 {
  /*
   * [初始化词法分析类的自动机集合]
   **/
  ExNFA tmp_exnfa;
  GenerateNFA( m_library_cores[i], tmp_exnfa ) ;

  m_dfaList.resize(m_dfaList.size()+1);

  /*
   * [名称化简,然后再转换为DFA]
   **/
  tmp_exnfa.ConvertToExDFA(m_dfaList.back());

  /*
   * [化简]
   **/
  DFAReduction::Reduction(m_dfaList.back(),m_dfaList.back());

  /*
   * [由于上面的自动机产生与下面的不产生冲突,因此重新设置ID值]
   **/
  // [说明,由于在生成NFA过程中会产生新的状态,程序中,我是通过一个唯一计数来产生唯一状态名的]
  TypeState::ResetID();
 }

接着在已经生成的正规定义式的自动机的基础上,根据识别规则生成不确定自动机——之所以没有转换为确定自动机是因为会导致许多的终态,最后才进行化简。

 for(unsigned int i=0; i<m_recginitions.size(); i++)
 {
  m_nfa_list.push_back(TypeExNFA());
  GenerateNFA( m_recginitions[i], m_nfa_list.back() );

  // [调试使用]
  // [string str = m_nfa_list.back().ToString();]
 }


上面两个部分我放在一个函数中完成,bool GenerateFA() ; 如果不是非常特殊情况,会返回true,因为函数中没有 return false;语句 :)。


这样各个分散的自动机便产生了,接着要把分散的合并为一个不确定自动机

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值