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

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

自動機

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

表達式

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

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

 

ε-NFA的狀態

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

在上面的代碼中,為了調試方便,我為其加入了idx域,并為每個狀態分配了一個唯一的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;
}
};

有了以上兩個結構之后,我們為Rule添加三個成員變量

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

 

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

生成狀態機

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

字符集

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

 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);
}

串聯關系

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

 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;
}

 

并聯關系

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

 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)*的兩種重復關系,對于這兩種重復關系,生成的狀態機的區別僅在于end狀態對于一次以上的重復,只需要給原狀態機添加一條從end狀態到start狀態的ε邊即可。而對于零次以上的重復,不光需要添加ε邊,同時需要將新狀態機的end狀態標記為start狀態,因為零次重復時不需要經過任意邊既可被接受。

 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;
}

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

一些拓展

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

可選關系

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

 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類型的字符集,應此對于取反我們只需要將當前狀態機內所有類型為TChar或TString類型的邊取一下反即可(需要注意的是可能存在負負得正的情況,既取偶數次反等于沒取反

 

 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]表達式。其實這是一種并聯關系的拓展,由兩個原始狀態機拓展到了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;
}

尾聲

讓我們來編寫一個函數來打印出整個生成后的狀態機。

 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

可打印出如下內容

狀態機

最后形成形如下圖的狀態機

狀態機圖

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

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

評論:
# re: 詞法分析器1(正則表達式到&epsilon;-NFA的轉換) 2013-02-17 18:29 | Zblc(邱震鈺)
一看標題 - -+ 果然是你發的。。  回復  更多評論
  
# 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>
            久久av老司机精品网站导航| 国产日韩欧美另类| 午夜精品久久久久影视| 亚洲视频一区二区在线观看| 亚洲精品一区二区三区婷婷月 | 性色av一区二区三区| 一区二区三区欧美激情| 亚洲无毛电影| 久久黄色小说| 浪潮色综合久久天堂| 欧美v亚洲v综合ⅴ国产v| 免费h精品视频在线播放| 欧美高清在线| 亚洲裸体俱乐部裸体舞表演av| 99视频热这里只有精品免费| 一本色道久久综合亚洲91| 亚洲欧美日韩一区二区在线| 久久综合999| 久久尤物视频| 一区二区三区久久网| 欧美一区二区黄| 欧美国产日韩a欧美在线观看| 亚洲欧洲日本在线| 在线综合亚洲欧美在线视频| 午夜日韩av| 欧美大尺度在线观看| 国产精品久久久免费| 在线观看欧美| 久久福利毛片| 亚洲精品你懂的| avtt综合网| 美女视频网站黄色亚洲| 国产日产欧产精品推荐色 | 一区二区日本视频| 久久国产欧美精品| 欧美午夜不卡在线观看免费| 一色屋精品亚洲香蕉网站| 一区二区三区**美女毛片| 久久久噜噜噜| 亚洲综合成人婷婷小说| 欧美精品午夜| 亚洲国产精品一区二区第一页| 亚洲女女女同性video| 91久久精品国产91久久| 久久久久综合一区二区三区| 国产精品免费一区二区三区在线观看 | 亚洲精华国产欧美| 久久久久九九视频| 国产亚洲精品v| 亚洲午夜女主播在线直播| 欧美丰满高潮xxxx喷水动漫| 午夜精品视频网站| 国产精品免费看片| 亚洲午夜一区二区三区| 亚洲人成高清| 欧美韩日一区二区三区| 亚洲国产欧美日韩| 免费看的黄色欧美网站| 久久成人国产精品| 国内精品免费午夜毛片| 欧美在线观看视频一区二区三区 | 亚洲精品免费在线播放| 欧美99在线视频观看| 在线观看视频一区| 免费毛片一区二区三区久久久| 欧美一区亚洲二区| 国一区二区在线观看| 久久理论片午夜琪琪电影网| 欧美在线日韩在线| 黑人巨大精品欧美黑白配亚洲| 久久精品五月| 久久性色av| 亚洲精品中文字幕有码专区| 91久久精品日日躁夜夜躁国产| 欧美国产精品专区| 亚洲一区区二区| 亚洲欧美在线网| 狠狠久久五月精品中文字幕| 久久香蕉精品| 欧美成人dvd在线视频| 日韩视频在线一区二区| 亚洲色图自拍| 韩国三级在线一区| 亚洲国产成人精品久久久国产成人一区| 久久免费99精品久久久久久| 亚洲国产成人久久综合| 亚洲精品永久免费| 国产日韩欧美二区| 亚洲电影自拍| 国产精品xxxav免费视频| 久久久久中文| 欧美激情综合在线| 久久精品国产亚洲一区二区| 久久香蕉国产线看观看网| 一区二区三区黄色| 欧美在线免费观看视频| 亚洲精品字幕| 亚洲免费视频成人| 在线播放亚洲| 亚洲色图自拍| 亚洲精品影视在线观看| 欧美在线亚洲综合一区| 亚洲免费成人av| 久久九九国产精品| 国产精品一二| 欧美高清视频www夜色资源网| 欧美三区在线观看| 农村妇女精品| 国产女人精品视频| 亚洲人成高清| 亚洲国产合集| 欧美综合二区| 性色av一区二区怡红| 欧美电影免费网站| 久久久久高清| 国产精品一二三四区| 亚洲精品欧洲| 亚洲精品欧洲精品| 久久久7777| 久久九九久久九九| 国产精品卡一卡二卡三| 亚洲激情校园春色| 在线欧美视频| 久久精品国产清高在天天线| 亚洲欧美日韩天堂一区二区| 欧美激情一区三区| 亚洲国产欧美日韩精品| 在线不卡亚洲| 久久免费黄色| 久久人人超碰| 国产一区三区三区| 性亚洲最疯狂xxxx高清| 亚洲在线一区二区| 欧美视频不卡| 亚洲视频在线观看视频| 亚洲自拍偷拍一区| 欧美区一区二| 亚洲欧洲在线观看| 亚洲精品综合久久中文字幕| 欧美大秀在线观看| 亚洲国产你懂的| 最新国产乱人伦偷精品免费网站 | 亚洲国产一区二区三区高清| 91久久在线| 欧美成人精品1314www| 亚洲第一福利在线观看| 亚洲日本va午夜在线影院| 欧美二区乱c少妇| 亚洲精品美女久久7777777| 一区二区三区成人精品| 欧美日韩在线综合| 亚洲视频在线一区观看| 欧美一区不卡| 狠狠色丁香婷婷综合影院 | 国产精品ⅴa在线观看h| 在线综合欧美| 久久久久久久综合色一本| 狠狠爱www人成狠狠爱综合网| 久久天堂成人| a4yy欧美一区二区三区| 久久国产乱子精品免费女| 黑人一区二区三区四区五区| 免费成人黄色av| 夜夜嗨av一区二区三区中文字幕| 亚洲欧美日韩专区| 精品av久久久久电影| 欧美福利影院| 亚洲欧美制服中文字幕| 欧美成人黑人xx视频免费观看| 亚洲精品一区二区在线观看| 欧美性猛交xxxx免费看久久久| 亚洲欧美日韩天堂| 影音先锋久久久| 欧美色视频在线| 久久久蜜臀国产一区二区| 亚洲欧洲精品一区二区三区不卡 | 亚洲手机视频| 久久综合亚洲社区| 一区二区三区欧美激情| 国产主播精品| 欧美日韩在线观看视频| 久久精品国产久精国产思思| 亚洲精品日韩在线观看| 久久精品国产亚洲一区二区三区 | 一本色道久久综合狠狠躁的推荐| 欧美专区亚洲专区| 夜夜嗨av色一区二区不卡| 韩国三级电影久久久久久| 欧美四级在线观看| 美女尤物久久精品| 先锋影音久久| 亚洲天堂偷拍| 日韩视频一区二区三区在线播放免费观看 | 亚洲黄色免费电影| 国产九九视频一区二区三区| 久久国产精品色婷婷| 中国成人黄色视屏| 欧美国产免费| 欧美在线视频一区| 亚洲经典视频在线观看|