我的目标只是按照课本上所说的,一个表格,一个控制程序,而控制程序大部分没什么变化,只是根据识别动作做相应的一点改变而
已,最后虽然完成了,但不能肯定它的正确性,还好多次测试都没什么问题……(简单的测试)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;语句 :)。
这样各个分散的自动机便产生了,接着要把分散的合并为一个不确定自动机