📅  最后修改于: 2023-12-03 15:02:40.682000             🧑  作者: Mango
在计算机科学中,确定的有限状态自动机(DFA)用于识别正则语言中的字符串。在这里,我们将使用LEX编写一个DFA,该DFA接受0的奇数和1的偶数。
我们先来定义这个正则表达式:
(1*01*01*)*0*
这里, (1*01*01*)*
表示在任何数量的1之间可以插入随意数量的0。我们用 0*
结尾,以接受任何数量的0。
下面是状态转换图:
0
---->
+-------+ | +-------+
| q0 | | | q1 |
--->|start |-----+---->|final 1|
+-------+ +-------+
| ^ 1 | ^ 0
| |__________ | |
v | v |
+-------+ | +-------+
| q2 | +--->| q3 |
|final 2| |final 3|
+-------+ +-------+
| ^ | ^
| |_________ | |
v | v |
0 --- | 1 ---|
<---+ |______| +--->
|
|_____0,1_____>
每个圆形表示DFA中的一个状态,并附有一个状态编号。在我们的DFA中,有4个状态,分别编号为q0、q1、q2和q3。
2个状态是最终状态(接受状态),分别编号为final 1和final 2,其他状态是非终态(不接受状态)。
从start状态出发,如果在遇到任何1之前,我们在其后跟随偶数个1和奇数个0,我们将进入final 1。如果在随后继续遇到任何数量的1和1之后的任何数量的0,那么我们将继续进入状态final 1。如果我们遇到偶数个1和奇数个0,我们将进入状态final 2。从任何状态,如果我们遇到0,我们将返回到开始状态q0。
下面是使用LEX编写的程序,该程序遵循上述状态转换图:
%{
// 定义状态
enum states {
START,
FINAL_ONE,
FINAL_TWO,
FINAL_THREE
};
%}
// 定义输入字符集(0或1)
%{
0 { return '0'; }
1 { return '1'; }
%}
%%
// 定义状态转换
{START} 0 {START}
{START} 1 {FINAL_ONE}
{FINAL_ONE} 0 {FINAL_TWO}
{FINAL_ONE} 1 {FINAL_THREE}
{FINAL_TWO} 0 {FINAL_ONE}
{FINAL_TWO} 1 {START}
{FINAL_THREE} 0 {FINAL_THREE}
{FINAL_THREE} 1 {FINAL_TWO}
// 忽略空格和换行
[ \n] {}
// 未定义的字符(非0和1)不被识别
. {}
%%
// main函数
int main() {
yylex();
return 0;
}
生成代码,编译它,然后运行它即可:
$ lex dfa.l
$ gcc lex.yy.c -o dfa -ll
$ ./dfa
这将启动程序,等待从标准输入中读取输入。随意键入0和1的组合(没有空格或换行符),如果输入符合我们的正则表达式,程序将在终端输出一条消息。 例如,
101
这将打印:
String accepted!
如果输入不符合正则表达式,程序将保持沉默,等待下一个字符串。 例如,
11110
这将打印:
这段代码演示了使用LEX编写DFA来识别正则语言的基础知识。 特别是,在此示例中,我们演示了如何识别0的奇数和1的偶数,并创建了一个状态转换图和LEX代码。 为了使用它,我们只需生成、编译和运行代码,然后输入希望检查其匹配性的字符串。