确定有限自动机(DFA)——一个简单的C++词法分析器
开始想运用确定有限自动机去实现一个简单的C++词法分析器时,我感到很困难,不知从何处下手,因为C++词法太多太复杂,并且为了体现c++的特性又不得不去对它的语法作一点引入。幸运的是,在搜索相关资料时,一位网友的关于用c++构造词法自动机文章帮我解决了心中的难题,在此万分感谢!。(作者原文地址:http://hi.baidu.com/peiwenlin/blog/item/8c768d31137024af5edf0e0e.html)我根据作者的代码以及自己的思路对程序重新进行了改造,具体改造如下:
(1)比较深入地阐述了DFA理论,给出了DFA的模拟程序;
(2)使程序能识别所有的C++关键字;
(3)增加了对特殊符号的识别,比如. ' ";
(4)增加了对c++注释符号//的识别;
(5)增加了对标识符的识别力度,如ID = (_ | letter)(letter | digit | _)* ;
(6)修正了专有符号命名与编译器系统命名的冲突,比如“<”映射成字符串LT,LT与宏IDAStatics_LT(This,a_0,b_1,ret_2)相冲突,尽管在win32控制台程序中未报错,但在MFC应用程序中却会报错,解决办法是在把LT改为LTEN(-EN即enum)。
(7)最大的创新是用MFC开发了一个图形化的C++词法分析器。
(8)最后是简化了原代码,比如删掉了无用的函数isReservedWords()。
前言
词法分析是编译的第一个阶段,它的主要任务是从左至右逐个字符地对源程序进行扫描,产生一个个单词序列,用以语法分析。实际上,词法也是语法的一部分,词法描述完全可以归并到语法描述中去,只不过词法规则更简单些。为什么将词法分析做为一个独立的阶段?为什么把编译过程的分析工作划分成词法分析和语法分析两个阶段?主要的考虑因素为: ① 使整个编译程序的结构更简洁、清晰和条理化。 ② 编译程序的效率会改进。 ③ 增强编译程序的可移植性。
词法分析程序的任务是:读源程序,产生单词符号;滤掉空格,跳过注释、换行符;追踪换行标志,复制出错源程序等等。
描述程序设计语言的词法的机制是正则表达式,识别机制是有穷状态自动机。
设计思想
DFA(确定的有穷自动机)定义:一个确定的有穷自动机(DFA)M是一个五元组:M=(K,Σ,f,S,Z)其中
① K是一个有穷集,它的每个元素称为一个状态;
② Σ是一个有穷字母表,它的每个元素称为一个输入符号,所以也称Σ为输入符号字母表;
③ f是转换函数,是K×Σ→K上的映射,即如 f(ki,a)=kj,(ki∈K,kj∈K)就意味着,
当前状态为ki,输入符为a时,将转换为下一个状态kj,我们把kj称作ki的一个后继状态;
④ S ∈ K是唯一的一个初态;
⑤ Z K是一个终态集,终态也称可接受状态或结束状态。
模拟DFA的程序思想如下伪代码示例:
K=S;
c=getchar();
while(c!=EOF)
{
K=f(K,c);
c=getchar();
}
if( K== Z )return TRUE
else return FALSE
C++的单词识别基本思想
标识符ID = (_ | letter)(letter | digit | _)*
数字NUM =digit*
字母letter = a|..|z|A|..|Z|
数字digit = 0|..|9
C++专用符号+ - * / < <= > >= == != = ; , . ' " ( ) [ ] { } /* */
C++语言的关键字(所有的关键字都是保留字,并且必须是小写)
auto const dynamic_cast for mutable register static_cast try virtual
bool const_cast else friend namespace reinterpret_cast struct typedef void
break continue enum goto new return switch typeid volatile
case default explicit if operator short template typename while
catch delete extern inline private si