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

隨筆-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)來說,我們并不需要知道他的任何信息

在上面的代碼中,為了調試方便,我為其加入了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)所經過的邊作為value的hash表。

生成狀態(tài)機

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

字符集

正如上文所說,字符集包括Char_Type和String_Type類型的字符,應此生成字符集的狀態(tài)機就比較簡單了,只需創(chuàng)建出兩個狀態(tài),然后通過一條經過這個字符集的邊將這兩個狀態(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),因為零次重復時不需要經過任意邊既可被接受。

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

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

一些拓展

下面來看看一些拓展形式的狀態(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)機內所有類型為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]表達式。其實這是一種并聯(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;
}

尾聲

讓我們來編寫一個函數來打印出整個生成后的狀態(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

可打印出如下內容

狀態(tài)機

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

狀態(tài)機圖

完整的代碼可到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(邱震鈺)
一看標題 - -+ 果然是你發(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>
            欧美国内亚洲| 亚洲精选久久| 99re6这里只有精品| 亚洲国产精品成人va在线观看| 狠狠色丁香婷婷综合| 1024国产精品| 亚洲毛片在线看| 亚洲欧美日韩在线综合| 久久精品亚洲一区二区| 欧美成人免费播放| 在线一区免费观看| 久久久97精品| 国产精品久久久久久av下载红粉| 国产精品国产三级国产普通话蜜臀 | 久久久999| 欧美日韩国产小视频在线观看| 欧美性猛交视频| 伊大人香蕉综合8在线视| 亚洲精品乱码视频| 性视频1819p久久| 免费在线亚洲欧美| 在线视频中文亚洲| 久久久精品性| 国产精品久久久久久久电影| 狠狠色狠狠色综合人人| 免费观看国产成人| 国产精品黄色在线观看| 伊人久久男人天堂| 亚洲一区3d动漫同人无遮挡| 久久尤物视频| 亚洲一区二区三区四区在线观看| 久久久久在线| 国产精品一区在线播放| 99精品福利视频| 免费成人黄色| 欧美一区二区精品| 欧美亚州一区二区三区| 亚洲人久久久| 暖暖成人免费视频| 亚洲欧洲av一区二区三区久久| 欧美日韩高清区| 亚洲电影激情视频网站| 欧美中文字幕第一页| 正在播放欧美视频| 欧美日韩在线一区| 夜夜嗨av一区二区三区网站四季av| 久久久久久久久久久久久9999| 99在线精品免费视频九九视| 免费中文字幕日韩欧美| 在线观看国产欧美| 蜜臀a∨国产成人精品| 午夜精品在线看| 国产热re99久久6国产精品| 国产精品99久久久久久有的能看| 亚洲高清免费在线| 久久久久久穴| 在线播放中文一区| 麻豆精品国产91久久久久久| 久久精品亚洲一区二区三区浴池 | 国产视频一区二区在线观看| 亚洲一区免费网站| 亚洲色图综合久久| 国产精品欧美日韩| 欧美一区二区三区免费看| 一二美女精品欧洲| 国产精品萝li| 久久久精品国产免大香伊| 香蕉免费一区二区三区在线观看| 国产日韩欧美一区二区三区四区| 久久久久久久999精品视频| 久久精品麻豆| 亚洲破处大片| 亚洲精品视频免费在线观看| 欧美视频免费看| 欧美一级在线视频| 久久成人免费网| 亚洲激情欧美| 一区电影在线观看| 国产无一区二区| 欧美激情精品久久久| 欧美日韩福利视频| 久久久久一区| 欧美国产日本在线| 亚洲综合第一| 久久久青草青青国产亚洲免观| 欧美国产激情| 欧美一二三区精品| 免费观看一区| 亚洲欧美一区二区三区久久| 欧美一区网站| 亚洲精品欧美日韩专区| 亚洲私人影吧| 亚洲丰满在线| 亚洲在线一区二区三区| 亚洲第一搞黄网站| 亚洲图片欧洲图片av| 在线看不卡av| 亚洲一区二区三区四区五区黄| 精品成人一区二区| 野花国产精品入口| 亚洲高清免费| 午夜精品在线视频| 亚洲一卡久久| 欧美精品123区| 老司机免费视频久久| 欧美日韩免费在线视频| 免费在线观看成人av| 欧美日韩综合另类| 亚洲电影在线| 韩国在线视频一区| 亚洲午夜电影网| 亚洲美女啪啪| 久久噜噜亚洲综合| 久久精品99国产精品| 欧美精品国产| 亚洲电影免费观看高清| 国产在线乱码一区二区三区| 日韩一级裸体免费视频| 亚洲精品国产精品乱码不99 | 亚洲午夜精品福利| 一区二区国产精品| 欧美成人精品不卡视频在线观看| 午夜精品久久久久久| 欧美日韩国产bt| 亚洲韩国青草视频| 在线日韩欧美| 久久蜜桃精品| 免费视频一区| 亚洲国产精品女人久久久| 久久精品免费播放| 久久永久免费| 在线国产精品播放| 免费不卡中文字幕视频| 免费不卡在线视频| 在线日本成人| 欧美高清不卡在线| 亚洲国产天堂网精品网站| 91久久精品国产91久久性色tv | 国产一区二区日韩| 午夜日韩福利| 久久裸体艺术| 一区二区在线视频播放| 久久亚洲影院| 91久久综合| 一区二区三区日韩| 国产精品美女主播| 欧美一区二区三区免费观看| 久久久久久久久久久一区| 禁断一区二区三区在线| 久久蜜臀精品av| 亚洲专区一区| 国产精品毛片va一区二区三区| 亚洲性视频网址| 久久精品视频导航| 亚洲风情亚aⅴ在线发布| 欧美精品久久天天躁| 在线一区二区三区四区五区| 久久9热精品视频| 亚洲第一成人在线| 欧美天天视频| 欧美一级在线视频| 欧美激情一区二区三区成人| 在线一区日本视频| 国产精品夜色7777狼人 | 亚洲综合视频一区| 欧美成人免费大片| 亚洲一区在线播放| 狠狠色丁香婷婷综合| 欧美国产先锋| 亚洲欧洲av一区二区三区久久| 欧美sm视频| 午夜日韩激情| 亚洲精品字幕| 国产精品一区二区久久久| 久久亚洲风情| 亚洲一区二区免费在线| 蘑菇福利视频一区播放| 在线亚洲欧美| 在线欧美日韩精品| 国产精品嫩草影院av蜜臀| 久久亚洲综合网| 亚洲欧美日本日韩| 亚洲黄色片网站| 久久精品中文| 亚洲自拍电影| 亚洲精选大片| 激情久久久久久| 国产精品亚洲第一区在线暖暖韩国| 老司机午夜免费精品视频 | 亚洲精品一区二区三区在线观看| 欧美一区二区三区视频| 日韩一级在线| 91久久久久久国产精品| 国内伊人久久久久久网站视频| 欧美色123| 欧美成人黄色小视频| 久久视频在线免费观看| 欧美一区久久| 久久成人资源| 香蕉亚洲视频|