- 概念
- 正则表达式
- NFA
使用bison来解析输入文件,将输入文件的规则区中的正则表达式转换为NFA图
典型的NFA状态图可见下面的示例
- DFA
NFA到DFA的计算过程:
- 从NFA图中得到每个对应DFA状态的NFA状态集合c1(每次转换一步)
- 求c1的epsilon闭包,得到一个新的NFA状态集合c2
- 根据c2求出一个对应的DFA状态,对应的节点集合为c3
重复步骤a-c,直至所有的转换都已完成(已无新的NFA状态集合),整个构造过程是动态的,NFA状态集合是动态计算得到,一旦有新的NFA状态集合求出,对应的DFA状态也对应增加
- 等价类
等价类(Equivalence Classes)指的是将输入字符根据规则需要分类,例如下面的例子EC总数为8;而meta-等价类(Meta-Equivalence Classes)则是用于模型机的(template),是一种更抽象的分类,如下面的例子meta-EC总数为3
- 转换表和转换算法
- 转换矩阵
根据上面DFA计算结果以及所有的等价类,求出从一个DFA状态转换到另一DFA状态的转换矩阵,两个转换状态的转换边(转换条件)为EC
DFA状态集合和转换矩阵可见下面的示例
- Template 和proto
Template 和proto用于减少转换表项的空间,及加速查找和转换过程;
两种表项均为双向链表
Template 和proto表项可见下面的示例
- 四个一维数组
- def
- base
- chk
- nxt
- 快速转换算法
/* mk1tbl - create table entries for a state (or state fragment) which
* has only one out-transition
*/
void mk1tbl( state, sym, onenxt, onedef )
int state, sym, onenxt, onedef;
{
if ( firstfree < sym )
firstfree = sym;
while ( chk[firstfree] != 0 )
if ( ++firstfree >= current_max_xpairs )
expand_nxt_chk();
base[state] = firstfree - sym;
def[state] = onedef;
chk[firstfree] = state;
nxt[firstfree] = onenxt;
if ( firstfree > tblend )
{
tblend = firstfree++;
if ( firstfree >= current_max_xpairs )
expand_nxt_chk();
}
}
或者:
base[statenum] = tblbase;
def[statenum] = deflink;
for (i = minec; i <= maxec; ++i)
if (state[i] != SAME_TRANS)
if (state[i] != 0 || deflink != JAMSTATE) {
nxt[tblbase + i] = state[i];
chk[tblbase + i] = statenum;
}
if (baseaddr == firstfree)
/* Find next free slot in tables. */
for (++firstfree; chk[firstfree] != 0; ++firstfree) ;
tblend = MAX (tblend, tbllast);
从以上的算法中可以看到firstfree= base[state]+sym(sym代表EC或者meta-EC),因此chk[firstfree] = chk[base[state]+sym] = state 如果成立,则表示存在这个转换表项,就将nxt[firstfree] = nxt[base[state]+sym] = onenxt 的值赋给next(下一表项)
- 一个例子:
- Test.l文件内容:
%%
if printf("KEY: %s\n",yytext);
[a-z][a-z0-9]* printf("ID: %s\n",yytext);
[0-9]+ printf("NUM: %s\n", yytext);
"/" printf("OPER: %s\n",yytext);
"*" printf("OPER: %s\n",yytext);
"/*"(.)*"*/" printf("ANNOTATION: %s\n",yytext);
%%
void main(int argc, char** argv)
{
yylex();
}
int yywrap()
{
return 1;
}
- 输出的各类表项:
G:\meterial\compiler\726lexYacc\flex-2.5.4a-1-src\src\flex\2.5.4a\flex-2.5.4a>flex.exe -T test.l
a.正则表达式
%%
1 if
2 [a-z][a-z0-9]*
3 [0-9]+
4 "\/"
5 "\*"
6 "\/\*"(.)*"\*\/"
7 End Marker
加上默认的“.”规则总共有7个规则
********** beginning dump of nfa with start state 38
state # 1 257: 0, 0
state # 2 257: 0, 0
state # 3 105: 4, 0
state # 4 102: 5, 0
state # 5 257: 0, 0 [1]
state # 6 257: 1, 3
state # 7 -1: 11, 0