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

隨筆-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 閱讀(2946) 評論(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>
            久久精品99无色码中文字幕 | 美女脱光内衣内裤视频久久影院 | 黑人一区二区三区四区五区| 亚洲精品综合精品自拍| 一本一本大道香蕉久在线精品| 欧美成人一品| 欧美激情国产日韩精品一区18| 亚洲高清视频一区二区| 老司机久久99久久精品播放免费| 久久视频免费观看| 欧美成ee人免费视频| 亚洲福利在线观看| 99在线精品观看| 亚洲欧美日韩精品久久久| 久久精品国产亚洲一区二区三区 | 欧美激情第8页| 欧美日韩亚洲一区二区三区在线 | 欧美在线www| 免费观看久久久4p| 亚洲缚视频在线观看| 亚洲视频欧美视频| 久久一区二区三区超碰国产精品| 欧美日韩精品| 韩国免费一区| 亚洲天堂av在线免费| 久久亚洲综合色| 亚洲精品日韩在线观看| 香蕉久久夜色精品| 欧美日韩国产一区二区三区地区| 国产一区清纯| 在线综合亚洲欧美在线视频| 可以免费看不卡的av网站| 日韩西西人体444www| 久久视频国产精品免费视频在线| 欧美吻胸吃奶大尺度电影| 在线看片一区| 国产精品日本一区二区| 久久精品国产免费观看| 欧美日韩高清在线观看| 激情婷婷欧美| 亚洲伊人久久综合| 亚洲国产网站| 久久九九热re6这里有精品 | 欧美国产日韩亚洲一区| 国产午夜精品麻豆| 亚洲午夜电影在线观看| 欧美黄色aaaa| 久久久www成人免费无遮挡大片| 欧美日韩精品一区| 亚洲激情另类| 免费观看一区| 欧美在线日韩| 国产模特精品视频久久久久| 亚洲亚洲精品在线观看| 91久久国产自产拍夜夜嗨| 久久久欧美一区二区| 国产一区二区三区久久久| 欧美一二区视频| 亚洲一区免费在线观看| 国产精品v欧美精品v日韩| 一区二区三区日韩精品视频| 亚洲欧洲一区二区三区| 欧美福利在线| 日韩一级精品| 日韩视频免费观看| 欧美日韩综合一区| 亚洲欧美综合v| 亚洲欧美日韩国产另类专区| 国产精品一区二区久久国产| 欧美一级在线视频| 性xx色xx综合久久久xx| 国产一区二区三区直播精品电影 | 国产亚洲福利一区| 久久久久久9| 看欧美日韩国产| 日韩午夜av电影| 一本色道综合亚洲| 国产精品萝li| 久久精品盗摄| 久热re这里精品视频在线6| 亚洲欧洲在线观看| 日韩午夜电影| 国产亚洲精品久久久| 欧美成人免费小视频| 欧美欧美天天天天操| 欧美亚洲视频在线观看| 久久九九免费| 一区二区三区高清在线| 欧美一区二区三区在线| 亚洲黄色三级| 亚洲午夜精品福利| 在线免费不卡视频| 夜夜嗨av一区二区三区四区| 狠狠干综合网| 欧美日韩亚洲91| 午夜综合激情| 久久天堂成人| 亚洲一二三级电影| 欧美在线三区| a91a精品视频在线观看| 亚洲综合视频1区| 亚洲国产高清一区| 亚洲主播在线观看| 亚洲国产精品成人综合| 夜夜嗨av一区二区三区免费区| 樱桃成人精品视频在线播放| 亚洲精品在线视频| 韩国成人福利片在线播放| 亚洲高清激情| 国产无一区二区| 日韩一级成人av| 在线免费观看日本欧美| 亚洲在线视频一区| 日韩视频在线免费| 久久久噜噜噜| 久久精品综合网| 国产精品美女在线观看| 亚洲日本成人网| 在线精品视频一区二区三四| 亚洲欧美色一区| 亚洲综合日本| 欧美日韩综合网| 亚洲茄子视频| 亚洲国产欧美一区| 欧美资源在线观看| 欧美一区二区高清| 国产精品超碰97尤物18| 亚洲精品一区二区三区99| 亚洲国产导航| 噜噜噜久久亚洲精品国产品小说| 久久久久久久久伊人| 国产午夜亚洲精品不卡| 亚洲免费在线视频| 欧美一区二区视频97| 国产精品日韩一区| 亚洲一区二区三区欧美| 亚洲欧美网站| 国产精品一区二区久久精品| 亚洲欧美一区二区三区极速播放 | 国产日韩欧美另类| 亚洲欧美日韩中文在线制服| 亚洲欧美日韩国产| 国产精品国色综合久久| 亚洲午夜在线| 久久国产精品色婷婷| 国产亚洲欧美日韩日本| 欧美在线综合| 欧美www视频| 亚洲高清激情| 欧美国产精品久久| 日韩一级在线| 午夜在线精品偷拍| 狠狠v欧美v日韩v亚洲ⅴ| 久久久久99| 亚洲国产精品免费| 亚洲一区二区三区四区在线观看| 欧美色图首页| 午夜国产精品影院在线观看| 欧美日韩国产首页| 亚洲视频精选| 欧美一区二区三区日韩视频| 国产综合色产在线精品| 久久欧美肥婆一二区| 亚洲激情网站| 午夜日韩福利| 亚洲国产精品黑人久久久 | 麻豆精品国产91久久久久久| 亚洲激情综合| 亚洲欧美中日韩| 激情久久久久久| 欧美日韩免费在线观看| 欧美在线国产精品| 亚洲激情国产精品| 久久精精品视频| 日韩视频在线你懂得| 国产婷婷精品| 欧美日韩黄色大片| 久久婷婷影院| 亚洲综合国产精品| 亚洲激情第一区| 久久亚洲欧洲| 亚洲欧美激情在线视频| 在线播放日韩专区| 国产精品video| 老司机午夜精品视频| 中国女人久久久| 亚洲国产高清在线| 久久久精品国产一区二区三区| 日韩视频免费| 伊人久久婷婷| 国产农村妇女精品一二区| 欧美chengren| 欧美在线视频全部完| 99精品欧美一区二区三区综合在线| 久久综合九色99| 欧美一级免费视频| 一本色道精品久久一区二区三区| 黄色精品在线看| 国产欧美精品一区aⅴ影院| 欧美日韩国产va另类|