編譯原理 正規表示式轉NFA

2021-10-03 02:51:21 字數 3548 閱讀 3649

從txt檔案中讀入正規表示式

#include

#include

#include

#include

#include

#define max_token 100

using

namespace std;

//詞struct token

;int

readtxt

(string filename,vector

&tokens)

//讀取正規表示式

string line;

//讀入的每一行

while

(getline

(input,line)

) temp.regexp=line.

substr

(i+1

,line.

size()

-i);

//獲取詞的正規表示式

tokens.

push_back

(temp);}

input.

close()

;return0;

}

把使用連線運算的地方換成「.」(符號可自定義),然後將中綴正規表示式轉成字尾表示式。

#include

#include

#include

#include

#include

#include

using

namespace std;

//把兩字元之間的連線加上.

string add_symbol

(string reg)

//a.( )

else

if(reg[i+1]

=='('

&®[i]

!='|'

&®[i]

!='(')}

return rege;

}//運算子優先順序表

char

*priorities=

;//運算子編號

intgetnum

(char c)

}//中綴轉字尾

string convert

(string reg)

//運算子處理

else

op.pop();

//彈出左括號,不輸出

break

;default

://優先順序大於棧頂優先順序

if(op.

top()==

'('||

(op.

top()!=

'('&&priorities[

getnum

(op.

top())

][getnum

(reg[i])]

=='//優先順序小於棧頂優先順序

else

op.push

(reg[i]);

}break;}

}}while

(!op.

empty()

) post.

pop_back()

;//去掉'#'

return post;

}

遇到字母,構建基本nfa(我這裡用cell資料結構表示),入棧

遇到運算子,出棧相應數量的nfa(如:| 作為雙目運算子,就要出棧兩個nfa),然後構建對應的nfa,入棧

#include

#include

#include

#include

#include

#include

#define max 5000

using

namespace std;

/*注意狀態總數量和狀態編號是不同的,因為狀態總數可能減少(連線運算),但編號是一直增下去的*/

int state_count=0;

//狀態的總數量

int nmbstate=1;

//狀態編號

int nullsymbol=0;

//輸入字元為?的邊的數量

struct state

;struct edge

;//單個nfa單元

struct cell

;//合併後正則的nfa

struct bigcell

;//單個字元nfa

cell makenfa

(char c)

//把s中的邊複製到t中

intedgescopy

(cell s,cell &t)

}//把s中的邊複製到t中

intedgescopy

(cell s,bigcell &t)

}//或運算nfa

cell ornfa

(cell left,cell right)

//連線運算nfa

cell andnfa

(cell left,cell right)

//改變結束狀態是right的開始狀態的邊

else

if(right.start.id==right.edges[i]

.target.id)

} right.start.id=left.end.id;

edgescopy

(right,left)

; left.end.id=right.end.id;

return left;

}//星閉包運算nfa

cell starnfa

(cell a)

cell reg2nfa

(string reg)

} current=s.

top();

s.pop();

return current;

}int

shownfa

(cell c)

cout<

return0;

}int

shownfa

(bigcell c)

cout<

return0;

}

因為最後要構建詞法分析器,所以做成乙個大的nfa後期識別會比較方便,因此可選擇將每個正規表示式的nfa合併為乙個大的。

具體方法是把新增乙個狀態0,把所有nfa的起點連起來。

//將各個正規表示式的nfa合併

bigcell mergenfa

(vectornfa)

return nfa;

}

輸入:數字、字母及自定義id的正規表示式

輸出:每一條邊的 起點 輸入字元(』?』 代表空) 終點

正規表示式轉NFA

最近一直在忙著寫大作業,考試複習,複習演算法的時候寫了一些隨筆,現在忙起來都落下了部落格,這裡有乙個vc 寫的大作業,主要是正規表示式轉nfa並顯示。內容如下。介紹一下nfa在表示的結構設計,由於nfa本身是一種有向圖,所以這裡的儲存結構設計和鄰接表相似,圖中的每個節點後面是一些與其連線的節點的值,...

正規表示式轉NFA

正規表示式有三種基本的運算 連線 concatenation 例如 abc,由a,b,c組成 聯合 union 例如 a b c,表示a或者b或者c kleene閉包 kleene 例如 ab 表示ab串不出現,或者出現1次或一次以上 其它的運算如 等都可以用以上三種基本運算或者運算的組合來表示。2...

編譯原理中的正規表示式 NFA和DFA

from 正規表示式,接觸得已經不少,各種語言都會有些正規表示式的庫來增強字串處理功能,這裡就編譯原理的詞法分析要用到的內容 下下。嗯,我很懶 還是課件截圖 這裡用遞迴定義來定義正則的,原因是簡潔方便,方便以後進一步學習,比如nfa。如果要說正規表示式的術語定義,又得找維基了,鏈結 在電腦科學中,是...