青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-91  評論-137  文章-0  trackbacks-0

自動機

關于自動機的說明,這里不不再復述,請到http://zh.wikipedia.org/wiki/自動機查看。

表達式

首先,我們規(guī)定表達式中只允許輸入Char_Type和String_Type類型的字符。

template <typename Char_Type, typename String_Type>
class Rule
{
};

 

ε-NFA的狀態(tài)

對于一個狀態(tài)來說,我們并不需要知道他的任何信息

在上面的代碼中,為了調(diào)試方便,我為其加入了idx域,并為每個狀態(tài)分配了一個唯一的ID。

 struct EpsilonNFA_State
{
#ifdef _DEBUG
uint idx;
EpsilonNFA_State()
{
idx = inc();
}
static uint inc()
{
static uint i = 0;
return i++;
}
#else
EpsilonNFA_State() {}
#endif
};

ε-NFA的邊

ε-NFA中的邊都是有向的。對于任意一條邊來說,最重要的是他的兩個端點是誰以及這條邊所對應的字符集(若這條邊不是ε邊)。

 struct EpsilonNFA_Edge
{
struct
{
Char_Type char_value;
String_Type string_value;
}data;
enum Edge_Type
{
TUnknown = 0,
TNot = 1,
TChar = 2,
TString = 4,
TEpsilon = 8
};
uchar edge_type;
EpsilonNFA_State* pFrom;
EpsilonNFA_State* pTo;
EpsilonNFA_Edge(EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TEpsilon), pFrom(pFrom), pTo(pTo) {}
EpsilonNFA_Edge(const Char_Type& x, EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TChar), pFrom(pFrom), pTo(pTo)
{
data.char_value = x;
}
EpsilonNFA_Edge(const String_Type& x, EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TString), pFrom(pFrom), pTo(pTo)
{
data.string_value = x;
}
inline void negate()
{
edge_type ^= TNot;
}
inline const bool isNot()const
{
return (edge_type & TNot) == TNot;
}
inline const bool isEpsilon()const
{
return (edge_type & TEpsilon) == TEpsilon;
}
inline const bool isChar()const
{
return (edge_type & TChar) == TChar;
}
inline const bool isString()const
{
return (edge_type & TString) == TString;
}
const Edge_Type edgeType()const
{
if (isEpsilon()) return TEpsilon;
else if (isChar()) return TChar;
else if (isString()) return TString;
else return TUnknown;
}
};

有了以上兩個結構之后,我們?yōu)镽ule添加三個成員變量

EpsilonNFA_State *pEpsilonStart, *pEpsilonEnd;
hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash> epsilonNFA_Edges;

 

pEpsilonStart和pEpsilonEnd分別表示這條表達式所對應狀態(tài)機的start和end狀態(tài),epsilonNFA_Edges則是以某個狀態(tài)作為key,從這個狀態(tài)到達另一個狀態(tài)所經(jīng)過的邊作為value的hash表。

生成狀態(tài)機

終于到了正題,首先,我們把所有的關系分為串聯(lián)關系、并聯(lián)關系、可選關系、0次及以上的重復關系、至少1次以上的重復關系和取反關系。下面分別介紹每種關系的ε-NFA如何來生成。(下文中若沒有指出連接邊的類型則是ε邊

字符集

正如上文所說,字符集包括Char_Type和String_Type類型的字符,應此生成字符集的狀態(tài)機就比較簡單了,只需創(chuàng)建出兩個狀態(tài),然后通過一條經(jīng)過這個字符集的邊將這兩個狀態(tài)按照某個方向連接,最后將一個狀態(tài)標記為start狀態(tài),另一個狀態(tài)標記為end狀態(tài)即可。

 Rule(const Char_Type& x, Context& context) : pDFAStart(NULL), context(context)
{
pEpsilonStart = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonStart);
pEpsilonEnd = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonEnd);
epsilonNFA_Edges[pEpsilonStart].push_back(EpsilonNFA_Edge(x, pEpsilonStart, pEpsilonEnd));
context.epsilonNFA_States.insert(pEpsilonStart);
context.epsilonNFA_States.insert(pEpsilonEnd);
}
Rule(const String_Type& x, Context& context) : pDFAStart(NULL), context(context)
{
pEpsilonStart = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonStart);
pEpsilonEnd = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonEnd);
epsilonNFA_Edges[pEpsilonStart].push_back(EpsilonNFA_Edge(x, pEpsilonStart, pEpsilonEnd));
context.epsilonNFA_States.insert(pEpsilonStart);
context.epsilonNFA_States.insert(pEpsilonEnd);
}

串聯(lián)關系

串聯(lián)關系中,只需要將前一個狀態(tài)機的end狀態(tài)通過ε邊連接到另一個狀態(tài)機的start狀態(tài),最后將前一個狀態(tài)的start狀態(tài)標記為新狀態(tài)機的start狀態(tài),后一個狀態(tài)機的end狀態(tài)標記為新狀態(tài)機的end狀態(tài)即可。

 self operator+(const self& x)
{
self a = cloneEpsilonNFA(*this), b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, b.pEpsilonStart));
a.pEpsilonEnd = b.pEpsilonEnd;
return a;
}

 

并聯(lián)關系

并聯(lián)關系中,需要分別新建一個start和end狀態(tài)做為新狀態(tài)機的start和end狀態(tài),然后將新生成的start狀態(tài)分別連接到原狀態(tài)機的start狀態(tài),原狀態(tài)機的end狀態(tài)連接到新生成的end狀態(tài)即可。

 self operator|(const self& x)
{
self a = cloneEpsilonNFA(*this), b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
EpsilonNFA_State* _pStart = EpsilonNFA_State_Alloc::allocate();
construct(_pStart);
EpsilonNFA_State* _pEnd = EpsilonNFA_State_Alloc::allocate();
construct(_pEnd);
context.epsilonNFA_States.insert(_pStart);
context.epsilonNFA_States.insert(_pEnd);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, a.pEpsilonStart));
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, b.pEpsilonStart));
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, _pEnd));
a.epsilonNFA_Edges[b.pEpsilonEnd].push_back(EpsilonNFA_Edge(b.pEpsilonEnd, _pEnd));
a.pEpsilonStart = _pStart;
a.pEpsilonEnd = _pEnd;
return a;
}

重復關系

在正則表達式中存在形如(a)+和(a)*的兩種重復關系,對于這兩種重復關系,生成的狀態(tài)機的區(qū)別僅在于end狀態(tài)對于一次以上的重復,只需要給原狀態(tài)機添加一條從end狀態(tài)到start狀態(tài)的ε邊即可。而對于零次以上的重復,不光需要添加ε邊,同時需要將新狀態(tài)機的end狀態(tài)標記為start狀態(tài),因為零次重復時不需要經(jīng)過任意邊既可被接受。

 self operator*()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges.insert(EpsilonNFA_Edge(a.pEpsilonEnd, a.pEpsilonStart));
a.pEpsilonEnd = a.pEpsilonStart;
return a;
}
self operator+()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, a.pEpsilonStart));
return a;
}

上面這三種是最基本的生成方法,通過以上這三種生成方法已足夠應付多數(shù)的表達式。

一些拓展

下面來看看一些拓展形式的狀態(tài)機是如何生成的。

可選關系

在可選關系中,只需要給原狀態(tài)機添加一條從start狀態(tài)到end狀態(tài)的ε邊即可。由于ε-NFA只允許有一個start和end狀態(tài)的關系,應此當條件不成立時從start狀態(tài)就可直接通過ε邊到達end狀態(tài)。

 inline self opt()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges[a.pEpsilonStart].push_back(EpsilonNFA_Edge(a.pEpsilonStart, a.pEpsilonEnd));
return a;
}

 

取反關系

由于我們只處理Char_Type和String_Type類型的字符集,應此對于取反我們只需要將當前狀態(tài)機內(nèi)所有類型為TChar或TString類型的邊取一下反即可(需要注意的是可能存在負負得正的情況,既取偶數(shù)次反等于沒取反

 

 self operator!()
{
self a = cloneEpsilonNFA(*this);
for (typename hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash>::iterator i = a.epsilonNFA_Edges.begin(), m = a.epsilonNFA_Edges.end(); i != m; ++i)
{
for (typename vector<EpsilonNFA_Edge>::iterator j = i->second.begin(), n = i->second.end(); j != n; ++j)
{
if (j->isChar() || j->isString()) j->negate();
}
}
return a;
}

 

 

Char-Char關系

所謂的char-char關系就是正則表達式中的[a-z]表達式。其實這是一種并聯(lián)關系的拓展,由兩個原始狀態(tài)機拓展到了N個,生成方法也類似。

 self operator-(const self& x)
{
self a = cloneEpsilonNFA(*this);
if (epsilonNFA_Edges.size() == 1 && x.epsilonNFA_Edges.size() == 1 &&
epsilonNFA_Edges.begin()->second.size() == 1 && x.epsilonNFA_Edges.begin()->second.size() == 1 &&
epsilonNFA_Edges.begin()->second.begin()->edge_type == EpsilonNFA_Edge::TChar && x.epsilonNFA_Edges.begin()->second.begin()->edge_type == EpsilonNFA_Edge::TChar)
{
EpsilonNFA_State* _pStart = EpsilonNFA_State_Alloc::allocate();
construct(_pStart);
EpsilonNFA_State* _pEnd = EpsilonNFA_State_Alloc::allocate();
construct(_pEnd);
context.epsilonNFA_States.insert(_pStart);
context.epsilonNFA_States.insert(_pEnd);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, a.pEpsilonStart));
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, _pEnd));
const Char_Type chStart = epsilonNFA_Edges.begin()->second.begin()->data.char_value;
const Char_Type chEnd = x.epsilonNFA_Edges.begin()->second.begin()->data.char_value;
for (Char_Type ch = chStart + 1; ch < chEnd; ++ch)
{
self y(ch, context);
copyEpsilonNFA_Edges(y, a);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, y.pEpsilonStart));
a.epsilonNFA_Edges[y.pEpsilonEnd].push_back(EpsilonNFA_Edge(y.pEpsilonEnd, _pEnd));
}
self b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, b.pEpsilonStart));
a.epsilonNFA_Edges[b.pEpsilonEnd].push_back(EpsilonNFA_Edge(b.pEpsilonEnd, _pEnd));
a.pEpsilonStart = _pStart;
a.pEpsilonEnd = _pEnd;
}
else
{
throw error<string>("doesn't support", __FILE__, __LINE__);
}
return a;
}

尾聲

讓我們來編寫一個函數(shù)來打印出整個生成后的狀態(tài)機。

 void printEpsilonNFA()
{
printf("-------- ε- NFA Start --------\n");
for (typename hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash>::const_iterator i = epsilonNFA_Edges.begin(), m = epsilonNFA_Edges.end(); i != m; ++i)
{
for (typename vector<EpsilonNFA_Edge>::const_iterator j = i->second.begin(), n = i->second.end(); j != n; ++j)
{
printf("%03d -> %03d", j->pFrom->idx, j->pTo->idx);
switch (j->edgeType())
{
case EpsilonNFA_Edge::TEpsilon:
printf("(ε)");
break;
case EpsilonNFA_Edge::TChar:
printf("(%c)", j->data.char_value);
break;
case EpsilonNFA_Edge::TString:
printf("(%s)", j->data.string_value.c_str());
break;
default:
break;
}
if (j->isNot()) printf("(not)");
printf("\n");
}
}
printf("start: %03d -> end: %03d\n", pEpsilonStart->idx, pEpsilonEnd->idx);
printf("--------- ε- NFA End ---------\n");
}

 

最后我們來編寫一些測試代碼來試試生成效果如何

Rule_Type::Context context;
Rule_Type a('a', context), b('b', context), d('d', context);
Rule_Type result = (a - d).opt() + (+b | !(a + b));
#ifdef _DEBUG
result.printEpsilonNFA();
#endif

可打印出如下內(nèi)容

狀態(tài)機

最后形成形如下圖的狀態(tài)機

狀態(tài)機圖

完整的代碼可到http://code.google.com/p/qlanguage下載。

posted on 2013-02-15 20:29 lwch 閱讀(2946) 評論(3)  編輯 收藏 引用 所屬分類: QLanguage

評論:
# re: 詞法分析器1(正則表達式到&epsilon;-NFA的轉換) 2013-02-17 18:29 | Zblc(邱震鈺)
一看標題 - -+ 果然是你發(fā)的。。  回復  更多評論
  
# re: 詞法分析器1(正則表達式到&epsilon;-NFA的轉換) 2013-02-18 22:28 | lwch
@Zblc(邱震鈺)
-.-這你都看的出  回復  更多評論
  
# re: 詞法分析器1(正則表達式到&epsilon;-NFA的轉換) 2013-02-19 12:47 | Richard Wei
支持下   回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲女性裸体视频| 久久手机精品视频| 欧美一区二区在线免费观看| 精品88久久久久88久久久| 国产一区再线| 在线不卡免费欧美| 亚洲高清三级视频| 红桃视频国产精品| 亚洲精品免费一区二区三区| 亚洲精品一级| 亚洲一区二区三区色| 久久久久国产精品www | 亚洲在线观看免费| 西西人体一区二区| 在线精品福利| 欧美日韩免费在线观看| 欧美日韩亚洲高清| 国产一区二区三区在线播放免费观看| 国产精品美女999| 国产精品一卡二卡| 99精品免费网| 美女精品在线观看| 91久久在线播放| 一本色道久久加勒比精品| 亚洲欧美资源在线| 欧美日韩mv| 亚洲精品1区| 久久久精品2019中文字幕神马| 日韩视频欧美视频| 欧美大胆成人| 亚洲三级电影全部在线观看高清| 久久精品一本| 欧美一级免费视频| 欧美日韩在线观看一区二区| 国内精品久久久久影院 日本资源| 亚洲图片在线观看| 亚洲人成网站精品片在线观看| 久久琪琪电影院| 亚洲国产精品悠悠久久琪琪| 久久久美女艺术照精彩视频福利播放 | 亚洲第一精品在线| 欧美一区二区观看视频| 欧美日韩一级视频| 午夜在线视频一区二区区别| 亚洲一区在线观看免费观看电影高清| 欧美日韩免费观看一区| 蜜臀久久久99精品久久久久久| 欧美视频一区| 欧美一区在线视频| 久久久爽爽爽美女图片| 日韩一级精品| 欧美夜福利tv在线| 亚洲美女色禁图| 亚洲调教视频在线观看| 一区二区三区中文在线观看| 亚洲国产精品va在线看黑人| 国产精品国产三级国产aⅴ9色| 久久精品夜色噜噜亚洲aⅴ| 久久九九国产精品| 亚洲综合精品自拍| 免费亚洲一区二区| 性感少妇一区| 欧美激情一区二区三区不卡| 欧美一区二区大片| 欧美激情免费观看| 欧美成人自拍| 国内视频精品| 欧美制服丝袜| 久久人人97超碰国产公开结果| 国产精品a级| 一区二区欧美精品| 99在线热播精品免费| 美国十次了思思久久精品导航| 欧美一区午夜精品| 国产农村妇女精品一区二区| 亚洲欧洲美洲综合色网| 99国产精品视频免费观看一公开| 久久久久9999亚洲精品| 久久亚洲色图| 亚洲品质自拍| 欧美日韩国产在线| 亚洲三级免费观看| 日韩午夜在线播放| 亚洲欧美日韩高清| 久久精品九九| 欧美成人精品在线观看| 国产精品影视天天线| 国产精品99久久久久久久女警| 亚洲视频一二区| 国产欧美一区二区白浆黑人| 香蕉久久久久久久av网站| 久久精品成人一区二区三区蜜臀| 国产欧美日韩在线观看| 久久永久免费| 一区二区三区精品久久久| 欧美在线free| 在线天堂一区av电影| 国模套图日韩精品一区二区| 欧美国产日本在线| 欧美一二三视频| 免费视频一区二区三区在线观看| 亚洲少妇在线| 亚洲激情成人网| 国产精品羞羞答答xxdd| 巨胸喷奶水www久久久免费动漫| 亚洲高清一区二区三区| 久久国产精品久久w女人spa| 亚洲美女视频在线观看| 国产综合精品| 国内精品国语自产拍在线观看| 欧美激情按摩| 欧美福利在线观看| 蜜臀av性久久久久蜜臀aⅴ四虎| 性伦欧美刺激片在线观看| 亚洲在线播放电影| 午夜精品久久| 久久久99精品免费观看不卡| 性欧美video另类hd性玩具| 亚洲欧美一区二区视频| 午夜精品久久久久久久99水蜜桃| 一区二区三区四区国产精品| 日韩亚洲欧美高清| 亚洲精品欧美激情| 在线精品福利| 91久久一区二区| 一区二区三区精品久久久| 亚洲精品综合久久中文字幕| 亚洲日本中文| 亚洲欧美视频在线| 久久婷婷av| 亚洲精品护士| 亚洲一区二区三区中文字幕在线 | 欧美大片在线看| 亚洲国产美国国产综合一区二区| 亚洲国产日韩一级| 一区二区三区精品国产| 久久野战av| 欧美日韩中国免费专区在线看| 国产精品亚洲不卡a| 亚洲国产精品va在线看黑人| 99www免费人成精品| 久久久www成人免费无遮挡大片| 亚洲黄网站在线观看| 久久成人免费电影| 国产精品www994| 亚洲黄色成人| 欧美国产三区| 你懂的视频欧美| 在线播放豆国产99亚洲| 久久激情五月婷婷| 9i看片成人免费高清| 美女诱惑一区| 亚洲欧洲在线一区| 暖暖成人免费视频| 欧美一区二区三区视频| 国产视频精品xxxx| 欧美一区二区福利在线| 亚洲欧美日韩国产精品| 国产美女搞久久| 久久精品在线播放| 欧美一级播放| 伊人激情综合| 在线日韩av| 久久久久www| 免费在线亚洲| 日韩午夜免费视频| 在线中文字幕一区| 国产日产欧美精品| 久久先锋资源| 欧美韩国日本一区| 亚洲免费在线| 久久偷窥视频| 亚洲手机视频| 性色av一区二区三区| 亚洲国产综合在线| 亚洲天天影视| 亚洲欧洲精品一区| 午夜在线成人av| 亚洲人体一区| 亚洲欧美三级伦理| 亚洲手机成人高清视频| 久久精品最新地址| 欧美一区二区三区久久精品茉莉花| 久久久久国产精品午夜一区| 中文亚洲字幕| 欧美精品在线视频| 91久久精品美女高潮| 伊人婷婷欧美激情| 欧美伊人影院| 久久久久久久999精品视频| 欧美三级视频在线| 在线午夜精品自拍| 亚洲欧美在线播放| 欧美日韩理论| 亚洲最新视频在线| 亚洲一区二区三区三| 国产精品久久激情| 亚洲欧美在线另类| 久久黄色级2电影| 在线观看三级视频欧美|