這個版本修改了前面版本的兩個個bug。
第乙個:識別到字符集的時候,只是將name_number加1,卻並不對reg_pattern_table[name_number]進行初始化。
第二個:識別到假名的時候,並不為他分配乙個name_number,而只是在hash表中為其分配乙個表項。
現在,當識別到這兩個的時候,都會為之分配乙個name_number,並在reg_pattern_table中正確的初始化。
相關的修改的**都在tackle_particle()函式中。
還有對tackle_cat()函式的定義移動到了tackle_invisible_cat()函式的前面。
另外乙個重大的修改就是,將當前檔案分割為多檔案了,原來的正則處理部分劃分為reg_preprocess.h。
而新的nfa生成部分為nfa_preocess.h。
nfa_process.h基本生成了nfa,但不是按照教科書進行的,具體方法可以看**,待會我會寫一篇文章來講我的方法。
1 #include "regular_preprocess.h"2
//這個版本終於要上nfa了,好興奮啊3//
由於連個節點之間可能有多條邊,所以只能用鄰接表來儲存了4//
注意這裡是有向圖5//
對於每乙個token,這裡都會生成乙個或多個圖節點6//
但是每個token會附帶另外的兩個域,即這個token的開始節點和結束節點7//
因為內部節點對於外部來說是不可連線的,所以不需要暴露8//
這裡有乙個難題,就是空轉換如何表示,這裡我們必須找乙個不可列印字元來代表空轉換9//
樓主自己查了一下asc碼表,選擇了17號字元,因為
10//
鬼才知道那個字元啥意思,而且看描述c語言裡面也不會出現這個字元吧,
11//
我看了看鍵盤,非常欣慰,因為我不知道怎麼打出17號字元
12//
好,就選它了。
13//
對於nfa圖,這裡維護了乙個圖節點的陣列,而這個陣列組成了鄰接表
14 typedef struct
_graph_edge_list
15graph_edge_list,*p_edge_list;
20 typedef struct _node_for_token//
對於每乙個token,我們記錄他的進入節點和終止節點,為了連線成大的nfa圖用
21node_for_token,pnode_for_token;
25 node_for_token token_node[100
];26
//每乙個token對應乙個節點,所以100就夠了,當然現在處理的是小的輸入
27//
注意這裡有乙個特殊的地方,對於括號運算子,他的內容與他的子節點的內容是一樣的
28//
而對於假名操作符,他的內容與他的子節點的內容也是一樣的,但是他的內容永遠都不會被其他節點所利用
29//
因為在生成token的過程中,入棧的是他所代表的子節點,所以他的token是不會被其他的token所引用的
30//
還有乙個最需要注意的地方,就是每乙個token都有其相對應的token_node,而且這兩者的索引都相同
31//
這個設定便利了nfa的處理,同時也就造就了上面說的括號與中括號的特殊性
32int token_node_number=1;//
這裡是用來遍歷整個token表的,每增加1,則token_node的內容增加1
33 p_edge_list nfa_node[400];//
因為生成nfa的過程中可能生成四倍於輸入的節點,所以定為這麼大
34int nfa_node_number=0;//
這個是nfa中的節點的標號
35void add_edge(int nfa_node_begin,int nfa_node_end,char label)//
新增邊的函式
3643
void generate_nfa_node(void)44
149 token_node_number++;
150break
;151
case
maybe_exist:
152//
處理問號運算子,其實這個就比較簡單了,只需要在子表示式的頭節點與尾節點之間加一條空邊
153 reg_pattern_origin=reg_pattern_table[token_node_number].sub;
154 add_edge_from=token_node[reg_pattern_origin].begin;
155 add_edge_to=token_node[reg_pattern_origin].end;
156 add_edge(add_edge_from,add_edge_to,(char)17
);157 token_node_number++;
158break
;159
case
one_or_more:
160//
這種情況下,我另外建立乙個節點當作本token的尾節點
161//
然後新增兩條空邊,起點都是子節點的尾節點,終點乙個是子節點的開始節點
162//
另外乙個就是當前節點的尾節點
163 nfa_node_number++;
164//
這個節點是作為當前節點的尾節點
165 nfa_node[nfa_node_number]=null;
166 token_node[token_node_number].end=nfa_node_number;
167 add_edge_to=nfa_node_number;
168 reg_pattern_origin=reg_pattern_table[token_node_number].sub;
169 add_edge_from=token_node[reg_pattern_origin].end;
170 add_edge(add_edge_from,add_edge_to,(char)17
);171 add_edge_to=token_node[reg_pattern_origin].begin;
172 add_edge(add_edge_from,add_edge_to,(char)17
);173 token_node_number++;
174break
;175
default
:176 printf("
a type can't be recognised, please check\n");
177 token_node_number++;
178break
;179
}180
}181 }
最初步的正規表示式引擎
這裡只是當作自己的 版本管理器使用,並不去詳細介紹 畢竟我的注釋裡面已經說明了很多。注意,當前的假定是輸入自己不能有錯誤,而且 這幾個操作符是保留字,其他的字元則當作其自身意思。當前不考慮轉義字元及三元組,以及不考慮子表示式命名,因此只能處理乙個長正規表示式。1 include 2 include ...
正規表示式初步
正規表示式是乙個特殊的字串行,它能幫助你方便的檢查乙個字串是否與某種模式匹配,python 自1.5版本起增加了re 模組,它提供 perl 風格的正規表示式模式。compile 函式根據乙個模式字串和可選的標誌引數生成乙個正規表示式物件。該物件擁有一系列方法用於正規表示式匹配和替換。1 基本常用的...
MySQL正規表示式初步
你還可以學習 mysql學習精粹 我們知道,在sql之中,可以用 like 這個謂詞 表示式 來進行模糊檢索,並支援 等佔位符.但是,這個模糊檢索的功能有很多限制,簡單來說就是太模糊了。在mysql中提供了 regexp 關鍵字來支援正規表示式,當然,只是一些很簡單的正則啦。首先,我們構造一些測試資...