计算DFA状态

时间:2013-05-22 17:37:50

标签: regex lex flex-lexer

我想使用FLEX计算某个正则表达式的DFA状态总数。哪些C文件或函数可以帮助我使用FLEX完成此任务?

1 个答案:

答案 0 :(得分:2)

如果您查看由flex生成的文件,那么yy_accept(和yy_base)中的条目数可能会很好地指示所使用的状态数生成DFA。如果您使用-Cf选项,则yy_nxt包含DFA的转换函数,表中的行数也是使用状态的数量。

您可能有不同版本的flex,其中表的命名方式不同,但很可能它们的名称非常相似。

在回答您的问题时:假设DFA已经最小化,DFA中的状态数量可以被认为是非常明确的。然而,转换次数的定义不太明确。

首先,flex对每个输入字符都有一个转换,因为它将ECHO任何不属于定义语言的字符。这是通过一个新的新状态来实现的。使用调试器可以反向设计这是哪种状态。但请注意,如果使用开始条件,则可能必须考虑存在多个此类状态的可能性。如果您想分析许多正则表达式,那么您可能需要查看其他一些工具或从flex获取来源并从那里开始。

在第二位flex有策略来最小化所有表的总大小。 -Cf选项指示它不这样做。一个这样的优化是找到字符的等价类,并且仅对每个字符类使用转换。输入字符首先被转换为其类,而后者又用于确定转换。因此,转换的数量要低得多,但确定字符类需要一个额外的表(请参阅yy_ec)。

因此,过渡次数是一个定义不太明确的概念。如果您对确定扫描仪的内存占用率感兴趣,那么我会查看扫描仪数据部分的大小。例如objdump -h文件上使用lex.yy.o.rodata部分的大小可以非常准确地估算表格的总大小。

您似乎已找到-v的{​​{1}}选项,它以更详细的形式提供DFA中的状态数。为了回答flex给出5个州的原因,您也可以使用"a" {}选项,因为它会在生成时为DFA提供。显然还有--trace规则,我认为它用于文件结束。对于每个开始条件,有两种状态,一种在线的开始处使用,一种在线的中间使用。这使得3个接受状态(一个用于End Marker,一个用于"a",一个用于End Marker)加上两个状态用于单个开始条件。

源文件(.|"\n")不是生成代码的一部分,但如果您觉得勇敢,您当然可以更改dfa.c的来源以进一步分析您自己的代码。我快速浏览了一下,似乎代码的生成与转换交织在一起,这使得它的模块化程度低于实验平台所需的模块化程度。还要注意K& R原型,它们可以有效地禁用对原型的任何类型检查。