OSDN Git Service

NGワードで特定の正規表現を使用するとフリーズする不具合を修正
[gikonavigoeson/gikonavi.git] / bmRegExp / bmregexp.pas
1 unit bmRegExp;
2 {******************************************************************************
3 \83^\83C\83g\83\8b      \81F\90³\8bK\95\\8c»\82ð\8eg\82Á\82½\95\8e\9a\97ñ\92T\8dõ/\91\80\8dì\83R\83\93\83|\81[\83l\83\93\83g\8fWver0.17
4 \83\86\83j\83b\83g\96¼    \81FbmRegExp.pas
5 \83o\81[\83W\83\87\83\93    \81Fversion 0.17
6 \93ú\95t          \81F2001/09/15
7 \93®\8dì\8am\94F\8aÂ\8b«  \81F  Windows 98 + Borland Delphi6 Japanese Personal edition
8 \8dì\8eÒ          \81F  \95õ\93\87 bmonkey \97Y\8e¡  ggb01164@nifty.ne.jp
9 \95Ï\8dX\97\9a\97ð      \81F  0.17    \83o\83O\8fC\90³ 2001/09/15
10               \81F    \81EMP3\82Ì\96\82\8fp\8et\82³\82ñ\82É\8b³\82¦\82Ä\92¸\82¢\82½\83\81\83\82\83\8a\83\8a\81[\83N\82Ì\8fC\90³\82ð\93K\97p\81B
11               \81F    \81E\82¨\82©\82Û\82ñ\82³\82ñ\82É\8b³\82¦\82Ä\92¸\82¢\82½\83\81\83\82\83\8a\83\8a\81[\83N\82Ì\8fC\90³\82ð\93K\97p\81B
12               \81F    \8fÚ\8d×\82Í\93¯\8d«\82Ìchangelog.html\82ð\8eQ\8fÆ\81B
13               \81F  0.16    \91æ\93ñ\8e\9f \88ê\94Ê\8cö\8aJ 1998/03/07
14               \81F    version 0.15 -> version 0.16
15               \81F    \81ETGrep\82Å\89p\91å\95\8e\9a/\8f¬\95\8e\9a\82ª\90³\82µ\82­\8c\9f\8dõ\82Å\82«\82È\82©\82Á\82½\83o\83O\82ð\8fC\90³\81B
16               \81F    \81E\8a¿\8e\9a\82Ì\83L\83\83\83\89\83N\83^\83N\83\89\83X\8ew\92è([\88\9f-ê¤]\82È\82Ç)\82Ì\83o\83O\82ð\8fC\90³\81B
17               \81F    \81EDelphi3, C++Builder1\82É\91Î\89\9e
18               \81F        \81E\83\86\83j\83b\83g\83t\83@\83C\83\8b\96¼\82ðRegExp.pas\82©\82çbmRegExp.pas\82É\95Ï\8dX
19               \81F        \81E\83R\83\93\83p\83C\83\89\82Ì\8cµ\82µ\82­\82È\82Á\82½\8c^\83`\83F\83b\83N\82É\91Î\89\9e
20               \81F        \81EMBUtils.pas\82ð\8eg\82í\82È\82¢\82æ\82¤\82É\95Ï\8dX\81B
21               \81F  0.15B   \83o\83O\8fC\90³\81ADelphi3\81AC++Builder1\91Î\89\9e
22               \81F  0.15    \88ê\94Ê\8cö\8aJ
23 \8eå\97v\83N\83\89\83X    \81F  TGrep, TAWKStr
24 \8cp\8f³\8aÖ\8cW      \81F  TObject
25
26 *******************************************************************************
27 \8eg\97p\95û\96@      \81F\83w\83\8b\83v\83t\83@\83C\83\8b\82Æ\83T\83\93\83v\83\8b\83v\83\8d\83W\83F\83N\83g\82ð\8eQ\8fÆ\82Ì\82±\82Æ
28 \95â\91«\90à\96¾      \81F
29
30 \92è\8b`\8c^        \81F
31
32 ******************************************************************************}
33
34 interface
35
36 uses
37   SysUtils, Classes, Windows, Forms
38 {$IFDEF DEBUG}
39   ,OutLine
40 {$ENDIF}
41   ;
42
43 type
44 { -========================== \97á\8aO\83N\83\89\83X =====================================-}
45 {TREParser \82ª\8fo\82·\97á\8aO\81B
46  ErrorPos \82É\82æ\82Á\82Ä\81A\90³\8bK\95\\8c»\95\8e\9a\97ñ\82Ì\89½\95\8e\9a\96Ú\82Å\97á\8aO\82ª\94­\90\82µ\82½\82©\82ð\8e¦\82·\81B}
47   ERegExpParser = class(Exception)
48   public
49     ErrorPos: Integer;
50     constructor Create(const Msg: string; ErrorPosition: Word);
51   end;
52 {-=============================                          ====================-}
53\82Q\83o\83C\83g\95\8e\9a\8c^}
54   WChar_t = Word;
55
56\82Q\83o\83C\83g\95\8e\9a\8c^\82Ö\82Ì\83|\83C\83\93\83^\8c^}
57   PWChar_t = ^WChar_t;
58
59 { WChar_t\8c\82Q\82Â\82Ô\82ñ\82Ì\8c^}
60   DoubleWChar_t = Integer;
61
62 { -====================== \95\8e\9a\97ñ\91\80\8dì\8aÖ\90\94 =====================================-}
63   {\90à\96¾ \81F  \82P\82U\90i\90\94\82ð\95\\82·\95\8e\9a\82ð\8eó\82¯\8eæ\82è\81A\90®\90\94\82É\82µ\82Ä\95Ô\82·\81B
64    \88ø\90\94 \81F  WCh: WChar_t;     16\90i\90\94\82ð\95\\82·1\83o\83C\83g\95\8e\9a [0-9a-fA-F]
65
66    \95Ô\82è\92l\81\90³\8fí\8e\9e\81F  0 <= result <= 15
67             \88Ù\8fí\8e\9e\81F  -1}
68   function HexWCharToInt(WCh: WChar_t): Integer;
69
70   {\90à\96¾ \81F  \82W\90i\90\94\82ð\95\\82·\95\8e\9a\82ð\8eó\82¯\8eæ\82è\81A\90®\90\94\82É\82µ\82Ä\95Ô\82·\81B
71    \88ø\90\94 \81F  WCh: WChar_t;     8\90i\90\94\82ð\95\\82·1\83o\83C\83g\95\8e\9a [0-7]
72
73    \95Ô\82è\92l\81\90³\8fí\8e\9e\81F  0 <= result <= 7
74             \88Ù\8fí\8e\9e\81F  -1}
75   function OctWCharToInt(WCh: WChar_t): Integer;
76
77   {\90à\96¾ \81F  16\90i\90\94\95\\8bL\82Ì\95\8e\9a\97ñ\82ðWord\8c^\82Ì\90\94\92l\82É\95Ï\8a·\82·\82é\81B
78   \88ø\90\94  \81F  Str: String     \95Ï\8a·\8c³\82Ì\95\8e\9a\97ñ
79             Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
80   \95\9b\8dì\97p\81F  \8f\88\97\9d\82µ\82½\83o\83C\83g\90\94\82¾\82¯Index\82ª\83C\83\93\83N\83\8a\83\81\83\93\83g\82³\82ê\82é\81B
81   \95Ô\82è\92l\81F  \95\8e\9a\97ñ\82ª\95\\82·Word\8c^\82Ì\92l}
82   function HexStrToInt(const Str: String; var Index: Integer): Word;
83
84   {\90à\96¾ \81F  \82W\90i\90\94\95\\8bL\82Ì\95\8e\9a\97ñ\82ðWord\8c^\82Ì\90\94\92l\82É\95Ï\8a·\82·\82é\81B
85   \88ø\90\94  \81F  Str: String     \95Ï\8a·\8c³\82Ì\95\8e\9a\97ñ
86             Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
87   \95\9b\8dì\97p\81F  \8f\88\97\9d\82µ\82½\83o\83C\83g\90\94\82¾\82¯Index\82ª\83C\83\93\83N\83\8a\83\81\83\93\83g\82³\82ê\82é\81B
88   \95Ô\82è\92l\81F  \95\8e\9a\97ñ\82ª\95\\82·Word\8c^\82Ì\92l}
89   function OctStrToInt(const Str: String; var Index: Integer): Word;
90
91   {\90à\96¾ \81\88ø\90\94Str\82©\82ç\82P\95\8e\9a\93Ç\82Ý\8fo\82·\81B
92   \93®\8dì  \81\88ø\90\94Str \82Ì\92\86\82Ì\88ø\90\94Index\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\82P\95\8e\9a\93¾\82Ä\81AIndex\82ð\91\9d\82â\82·\81B
93   \88ø\90\94  \81F Str:    String;    \82Q\83o\83C\83g\95\8e\9a\83R\81[\83h\82ð\8aÜ\82ñ\82¾String
94            Index:  Integer;   \95\8e\9a\82ð\93Ç\82Ý\8fo\82·\88Ê\92u\82Ì\90æ\93ª\82©\82ç\82Ì\83o\83C\83g\90\94
95   \95Ô\82è\92l\81\93Ç\82Ý\8fo\82µ\82½ WChar_t\8c^\82Ì\92l
96   \95\9b\8dì\97p\81F
97   \92\8d\88Ó  \81F Index\82ª\95\8e\9a\97ñ\82Ì\92·\82³\82æ\82è\82·\82Å\82É\92·\82¢\8fê\8d\87\82Í\8fí\82É WChType.Null\82ð\95Ô\82µ\81AIndex\82ð\91\9d\82â\82³\82È\82¢\81B
98           \82Â\82Ü\82è\81AIndex\82Í\8dÅ\91å\82Å\82à Length(Str)+1 \82Å\82 \82é\81B}
99   function GetWChar(const Str: String;var Index: Integer): WChar_t;
100
101   {\8b@\94\\81F GetWChar\83\81\83\\83b\83h\82É\82æ\82Á\82Ä\90i\82ñ\82¾ Index\82ð\82P\95\8e\9a\95ª\96ß\82·(1\81`\82Q\83o\83C\83g)
102    \92\8d\88Ó\81\83k\83\8b\81E\83L\83\83\83\89\83N\83^(GetWChar\82Ì\95Ô\82è\92l WChType.Null)\82ð\96ß\82·\82±\82Æ\82Í\82Å\82«\82È\82¢\81B}
103   procedure UnGetWChar(const Str: String; var Index: Integer);
104
105
106   {\8b@\94\\81F GetWChar\82ÌPChar\8c^\83o\81[\83W\83\87\83\93}
107   function PCharGetWChar(var pText: PChar): WChar_t;
108
109   {\8b@\94\\81F WChar_t\8c^\82Ì\92l\82ðString\8c^\82Ö\95Ï\8a·\82·\82é\81B}
110   function WCharToStr(WCh: WChar_t): String;
111
112   {\8b@\94\\81F '\' \82Å \88ø\97p\82³\82ê\82½\83L\83\83\83\89\83N\83^\82ð\93¾\82é\81B \n, \t \\ ...
113    \92\8d\88Ó\81F Index\82Í'\'\82Ì\8e\9f\82Ì\95\8e\9a\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82·\82é\81B}
114   function GetQuotedWChar(const Str: String; var Index: Integer): WChar_t;
115
116
117   {\90à\96¾ \81F  FS:WChar_t\82ð\8bæ\90Ø\82è\95\8e\9a\82Æ\82µ\82Ä\81A\83o\83C\83g\88Ê\92uIndex\82©\82ç\8en\82Ü\82é\83g\81[\83N\83\93\82ð\82P\82Â\95Ô\82·\81B
118   \88ø\90\94  \81F  Str: String
119             Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
120   \95Ô\82è\92l\81F  FS\82Å\8bæ\90Ø\82ç\82ê\82½\81A\83o\83C\83g\88Ê\92uIndex\82©\82ç\8en\82Ü\82é\83g\81[\83N\83\93}
121   function WCharGetToken(const Str: String; var Index: Integer; FS: WChar_t): String;
122
123
124   {\90à\96¾ \81F  \88ø\90\94Str\92\86\82Ì\83\81\83^\83L\83\83\83\89\83N\83^\82É'\'\82ð\82Â\82¯\82é\81B
125   \88ø\90\94  \81F  Str: String
126   \95Ô\82è\92l\81F  \83\81\83^\83L\83\83\83\89\83N\83^\82Ì\91O\82É'\'\82ª\82Â\82¢\82½Str}
127   function QuoteMetaWChar(Str: String): String;
128
129 const
130   CONST_DOLLAR  = $24;    //  '$'
131   CONST_LPAR    = $28;    //  '('
132   CONST_RPAR    = $29;    //  ')'
133   CONST_STAR    = $2A;    //  '*'
134   CONST_PLUS    = $2B;    //  '+'
135   CONST_DOT     = $2E;    //  '.'
136   CONST_QMARK   = $3F;    //  '?'
137   CONST_VL      = $7C;    //  '|'
138
139   CONST_LBRA    = $5B;    //  '['
140   CONST_RBRA    = $5D;    //  ']'
141   CONST_CARET   = $5E;    //  '^'
142   CONST_YEN     = $5C;    //  '\'
143   CONST_MINUS   = $2D;    //  '-'
144
145   CONST_b       = $62;      //  'b'
146   CONST_r       = $72;      //  'r'
147   CONST_n       = $6E;      //  'n'
148   CONST_t       = $74;      //  't'
149   CONST_x       = $78;      //  'x'
150
151   CONST_BS      = $08;      //  BackSpace
152   CONST_CR      = $0D;      //  Carriage Return
153   CONST_LF      = $0A;      //  Line Feed
154   CONST_TAB     = $09;      //  TAB
155
156   CONST_ANP     = $26;      //  '&'
157
158   CONST_NULL    = $0000;
159
160   METACHARS: Array[0..11] of WChar_t = (CONST_CARET,
161                                         CONST_LPAR,
162                                         CONST_VL,
163                                         CONST_RPAR,
164                                         CONST_PLUS,
165                                         CONST_STAR,
166                                         CONST_QMARK,
167                                         CONST_DOT,
168                                         CONST_LBRA,
169                                         CONST_RBRA,
170                                         CONST_DOLLAR,
171                                         CONST_YEN);
172
173   CONST_EMPTY    = $FFFF; {TNFA, TDFA\8fó\91Ô\95\\82Å\81u\95\8e\9a\82ª\82È\82¢\81v\82±\82Æ\82ð\95\\82·\83R\81[\83h\82Æ\82µ\82Ä\8eg\82¤}
174   CONST_LINEHEAD = $FFFD; {\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^'^'\82ð\95\\82·\95\8e\9a\83R\81[\83h\82Æ\82µ\82Ä\8eg\82¤\81B}
175   CONST_LINETAIL = $FFFE; {\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^'$'\82ð\95\\82·\95\8e\9a\83R\81[\83h\82Æ\82µ\82Ä\8eg\82¤\81B}
176
177   REFuzzyWChars: array [0..144] of String =
178     ('\82`,\82\81,A,a',
179      '\82a,\82\82,B,b',
180      '\82b,\82\83,C,c',
181      '\82c,\82\84,D,d',
182      '\82d,\82\85,E,e',
183      '\82e,\82\86,F,f',
184      '\82f,\82\87,G,g',
185      '\82g,\82\88,H,h',
186      '\82h,\82\89,I,i',
187      '\82i,\82\8a,J,j',
188      '\82j,\82\8b,K,k',
189      '\82k,\82\8c,L,l',
190      '\82l,\82\8d,M,m',
191      '\82m,\82\8e,N,n',
192      '\82n,\82\8f,O,o',
193      '\82o,\82\90,P,p',
194      '\82p,\82\91,Q,q',
195      '\82q,\82\92,R,r',
196      '\82r,\82\93,S,s',
197      '\82s,\82\94,T,t',
198      '\82t,\82\95,U,u',
199      '\82u,\82\96,V,v',
200      '\82v,\82\97,W,w',
201      '\82w,\82\98,X,x',
202      '\82x,\82\99,Y,y',
203      '\82y,\82\9a,Z,z',
204      '0,\82O,\97ë',
205      '1,\82P,\88ê,\87@,\87T,\88ë',
206      '2,\82Q,\93ñ,\87A,\87U,\93ó',
207      '3,\82R,\8eO,\87B,\87V,\8eQ',
208      '4,\82S,\8el,\87C,\87W',
209      '5,\82T,\8cÜ,\87D,\87X,\8cÞ',
210      '6,\82U,\98Z,\87E,\87Y',
211      '7,\82V,\8eµ,\87F,\87Z',
212      '8,\82W,\94ª,\87G,\87[',
213      '9,\82X,\8bã,\87H,\87\',
214      '"\81@"," "',
215      '!,\81I',
216      '"""",\81h',
217      '#,\81\94',
218      '$,\81\90',
219      '%,\81\93',
220      '&,\81\95',
221      ''',\81f',
222      '(,\81i',
223      '),\81j',
224      '*,\81\96',
225      '+,\81{',
226      '\81[,\81`,°,',   { \92·\89¹\8bL\8d\86\82Í\81A''\83k\83\8b\82Æ\82à\88ê\92v\82³\82¹\82é}
227      '-,\81[,\81|,\81`,°',
228      '¥,\81E',
229      '/,\81^',
230      ':,\81F',
231      ';,\81G',
232      '<,\81\83',
233      '=,\81\81',
234      '>,\81\84',
235      '?,\81H',
236      '@,\81\97',
237      '[,\81m,\81k',
238      '\,\81\8f',
239      '],\81n,\81l',
240      '^,\81O',
241      '_,\81Q',
242      '{,\81o',
243      '|,\81b',
244      '},\81p',
245      '~,\81P',
246      '",",¤,\81A,\81C',
247      '¡,.,\81B,\81D',
248      '\81u,\81w,¢',
249      '\81v,\81x,£',
250      '\82ñ,\83\93,Ý',
251      '\82ª,\83K,¶Þ,\82©\81J,\83J\81J',
252      '\82¬,\83M,·Þ,\82«\81J,\83L\81J',
253      '\82®,\83O,¸Þ,\82­\81J,\83N\81J',
254      '\82°,\83Q,¹Þ,\82¯\81J,\83P\81J',
255      '\82²,\83S,ºÞ,\82±\81J,\83R\81J',
256      '\82´,\83U,»Þ,\82³\81J,\83T\81J',
257      '\82¶,\83W,¼Þ,\82µ\81J,\83V\81J,\82À,\83a,ÁÞ,\82¿\81J,\83`\81J',
258      '\82¸,\83Y,½Þ,\83X\81J,\83X\81J,\82Ã,\83d,ÂÞ,\82Â\81J,\83c\81J',
259      '\82º,\83[,¾Þ,\82¹\81J,\83Z\81J',
260      '\82¼,\83],¿Þ,\82»\81J,\83\\81J',
261      '\82¾,\83_,ÀÞ,\82½\81J,\83^\81J',
262      '\82Å,\83f,ÃÞ,\82Ä\81J,\83e\81J',
263      '\82Ç,\83h,ÄÞ,\82Æ\81J,\83g\81J',
264      '\82Î,\83o,ÊÞ,\82Í\81J,\83n\81J,\83\94\83@,\82¤\81J\82\9f,\83E\81J\83@,³Þ§',
265      '\82Ñ,\83r,ËÞ,\82Ð\81J,\83q\81J,\83\94\83B,\82¤\81J\82¡,\83E\81J\83B,³Þ¨',
266      '\82Ô,\83u,ÌÞ,\82Ó\81J,\83t\81J,\83\94,\83E\81J,\82¤\81J,³Þ',
267      '\82×,\83x,ÍÞ,\82Ö\81J,\83w\81J,\83\94\83F,\82¤\81J\82¥,\83E\81J\83F,³Þª',
268      '\82Ú,\83{,ÎÞ,\82Ù\81J,\83z\81J,\83\94\83H,\82¤\81J\82§,\83E\81J\83H,³Þ«',
269      '\82Ï,\83p,Êß,\82Í\81K,\83n\81K',
270      '\82Ò,\83s,Ëß,\82Ð\81K,\83q\81K',
271      '\82Õ,\83v,Ìß,\82Ó\81K,\83t\81K',
272      '\82Ø,\83y,Íß,\82Ö\81K,\83w\81K',
273      '\82Û,\83|,Îß,\82Ù\81K,\83z\81K',
274      '\82 ,\83A,±,\82\9f,\83@,§',
275      '\82¢,\83C,²,\82¡,\83B,¨',
276      '\82¤,\83E,³,\82£,\83D,©',
277      '\82¦,\83G,´,\82¥,\83F,ª',
278      '\82¨,\83I,µ,\82§,\83H,«',
279      '\82©,\83J,¶',
280      '\82«,\83L,·',
281      '\82­,\83N,¸',
282      '\82¯,\83P,¹',
283      '\82±,\83R,º',
284      '\82³,\83T,»',
285      '\82µ,\83V,¼',
286      '\82·,\83X,½',
287      '\82¹,\83Z,¾',
288      '\82»,\83\,¿',
289      '\82½,\83^,À',
290      '\82¿,\83`,Á',
291      '\82Â,\83c,Â,\82Á,\83b,¯',
292      '\82Ä,\83e,Ã',
293      '\82Æ,\83g,Ä',
294      '\82È,\83i,Å',
295      '\82É,\83j,Æ',
296      '\82Ê,\83k,Ç',
297      '\82Ë,\83l,È',
298      '\82Ì,\83m,É',
299      '\82Í,\83n,Ê',
300      '\82Ð,\83q,Ë',
301      '\82Ó,\83t,Ì',
302      '\82Ö,\83w,Í',
303      '\82Ù,\83z,Î',
304      '\82Ü,\83},Ï',
305      '\82Ý,\83~,Ð',
306      '\82Þ,\83\80,Ñ',
307      '\82ß,\83\81,Ò',
308      '\82à,\83\82,Ó',
309      '\82â,\83\84,Ô,\82á,\83\83,¬',
310      '\82ä,\83\86,Õ,\82ã,\83\85,­',
311      '\82æ,\83\88,Ö,\82å,\83\87,®',
312      '\82ç,\83\89,×',
313      '\82è,\83\8a,Ø',
314      '\82é,\83\8b,Ù',
315      '\82ê,\83\8c,Ú',
316      '\82ë,\83\8d,Û',
317      '\82í,\83\8f,Ü,\82¤\82\9f,\83E\83@,³§',
318      '\83\90,\82î,\82¤\82¡,\83E\83B,³¨',
319      '\83\91,\82ï,\82¤\82¥,\83E\83F,³ª',
320      '\82ð,\83\92,¦,\82¤\82§,\83E\83H,³«',
321      'Þ,\81J',
322      'ß,\81K'); {\91÷\93_\81A\94¼\91÷\93_\82Í\82±\82Ì\88Ê\92u\82É\82È\82¢\82Æ \81h\82ª\81h\81¨\81h¶Þ\81h\82É\95Ï\8a·\82³\82ê\82È\82¢\81B}
323
324 type
325 { -============================= TREScanner Class ==================================-}
326   { \95\8e\9a\82Ì\94Í\88Í\82ð\95\\82·\8c^\81B}
327   RECharClass_t = record
328     case Char of
329     #0: (StartChar: WChar_t; EndChar: WChar_t);
330     #1: (Chars: DoubleWChar_t);
331   end;
332
333 const
334   CONST_EMPTYCharClass: RECharClass_t = ( StartChar: CONST_EMPTY;
335                                           EndChar: CONST_EMPTY);
336
337 type
338
339   { RECharClass_t\82Ö\82Ì\83|\83C\83\93\83^\8c^}
340   REpCharClass_t = ^RECharClass_t;
341
342   {\83g\81[\83N\83\93\82Ì\8eí\97Þ\82ð\95\\82·\8c^ }
343   REToken_t = ( retk_Char,      {\92Ê\8fí\82Ì\95\8e\9a  }
344                 retk_CharClass, {'[]'\82Å\88Í\82Ü\82ê\82½\83L\83\83\83\89\83N\83^\83N\83\89\83X\90³\8bK\95\\8c»\82Ì\92\86\82Å
345                                  '-'\82ð\8eg\82Á\82Ä\94Í\88Í\8ew\92è\82³\82ê\82½\95¨ }
346                 retk_Union,     { '|'}
347                 retk_LPar,      { '('}
348                 retk_RPar,      { ')'}
349                 retk_Star,      { '*'}
350                 retk_Plus,      { '+'}
351                 retk_QMark,     { '?'}
352                 retk_LBra,      { '['}
353                 retk_LBraNeg,   { '[\81O'}
354                 retk_RBra,      { ']'}
355                 retk_Dot,       { '.'}
356                 retk_LHead,     { '^'}
357                 retk_LTail,     { '$'}
358                 retk_End);      { \95\8e\9a\97ñ\82Ì\8fI\82í\82è }
359
360   { REToken_t\82Ì\8fW\8d\87\8fW\8d\87\8c^}
361   RETokenSet_t = set of REToken_t;
362
363   RESymbol_t = record
364     case REToken_t of
365       retk_CharClass: (CharClass: RECharClass_t);
366       retk_Char:      (WChar: WChar_t);
367   end;
368
369 {\81\9c \95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82·\83N\83\89\83X}
370   TREScanner = class
371   private
372     FRegExpStr: String;
373     FIndex: Integer;
374     FToken: REToken_t;
375     FSymbol: RESymbol_t;
376     FInCharClass: Boolean;
377   protected
378     procedure SetRegExpStr(RegExpStr: String);
379
380     {\8e\9f\82Ì\83g\81[\83N\83\93\82ð\93¾\82é\81B}
381     function GetTokenStd: REToken_t; virtual;
382     {\83L\83\83\83\89\83N\83^\83N\83\89\83X\90³\8bK\95\\8c» "[ ]" \82Ì\92\86\82Ì\83g\81[\83N\83\93\82ð\93¾\82é\81B}
383     function GetTokenCC: REToken_t; virtual;
384   public
385     constructor Create(Str: String);
386
387     function GetToken: REToken_t;
388
389     {\8c»\8dÝ\82Ì\83g\81[\83N\83\93}
390     property Token: REToken_t read FToken;
391
392     { Token\82É\91Î\89\9e\82·\82é\95\8e\9a[\97ñ](Lexeme)
393       Token <> retk_CharClass \82Ì\82Æ\82« \8c»\8dÝ\82Ì\83g\81[\83N\83\93\82Ì\95\8e\9a\92l WChar_t\8c^
394       Token =  retk_CharClass \82Ì\82Æ\82«\82ÍRECharClass_t\83\8c\83R\81[\83h\8c^
395       \81¦FToken = retk_LBraNeg\82Ì\8e\9e\82Í\83u\83\89\83P\83b\83g'['\82P\95\8e\9a\95ª\82µ\82©\82È\82¢\81B}
396     property Symbol: RESymbol_t read FSymbol;
397
398     {\8f\88\97\9d\91Î\8fÛ\82Ì\95\8e\9a\97ñ}
399     property RegExpStr: String read FRegExpStr write SetRegExpStr;
400
401     {\83C\83\93\83f\83b\83N\83X
402      InputStr\95\8e\9a\97ñ\92\86\82Å\8e\9f\82ÌGetWChar\83\81\83\\83b\83h\82Å\8f\88\97\9d\82·\82é\95\8e\9a\82Ì\83C\83\93\83f\83b\83N\83X
403      \81¦ Symbol\82Ì\8e\9f\82Ì\95\8e\9a\82ð\8ew\82µ\82Ä\82¢\82é\82±\82Æ\82É\92\8d\88Ó}
404     property Index: Integer read FIndex;
405   end;
406
407 {-=============================                          ====================-}
408   {\83g\81[\83N\83\93\82Ì\8fî\95ñ\82ð\82Ð\82Æ\82Ü\82Æ\82ß\82É\82µ\82½\82à\82Ì}
409   RETokenInfo_t = record
410     Token: REToken_t;
411     Symbol: RESymbol_t;
412     FromIndex: Integer;
413     ToIndex: Integer;
414   end;
415
416   REpTokenInfo_t = ^RETokenInfo_t;
417
418   {TREPreProcessor\83N\83\89\83X\93à\95\94\82Å\8eg\97p}
419   TREPreProcessorFindFunc = function(FromTokenIndex, ToTokenIndex: Integer): Integer of object;
420
421   TREPreProcessor = class
422   private
423     FScanner: TREScanner;
424     FProcessedRegExpStr: String;
425     FListOfSynonymDic: TList;
426     FListOfFuzzyCharDic: TList;
427     FTokenList: TList;
428     FSynonymStr: String;
429
430     FUseFuzzyCharDic: Boolean;
431     FUseSynonymDic: Boolean;
432   protected
433     procedure MakeTokenList;
434     procedure DestroyTokenListItems;
435
436     function ReferToOneList(FromTokenIndex, ToTokenIndex: Integer; SynonymDic: TList): Integer;
437     function FindSynonym(FromTokenIndex, ToTokenIndex: Integer): Integer;
438     function FindFuzzyWChar(FromTokenIndex, ToTokenIndex: Integer): Integer;
439
440     procedure Process(FindFunc: TREPreProcessorFindFunc);
441
442     function GetTargetRegExpStr: String;
443     procedure SetTargetRegExpStr(Str: String);
444   public
445     constructor Create(Str: String);
446     destructor  Destroy; override;
447     procedure   Run;
448
449     property    TargetRegExpStr: String read GetTargetRegExpStr write SetTargetRegExpStr;
450     property    ProcessedRegExpStr: String read FProcessedRegExpStr;
451
452     property    UseSynonymDic:      Boolean read FUseSynonymDic write FUseSynonymDic;
453     property    ListOfSynonymDic:   TList   read FListOfSynonymDic;
454     property    UseFuzzyCharDic:    Boolean read FUseFuzzyCharDic write FUseFuzzyCharDic;
455     property    ListOfFuzzyCharDic: TList   read FListOfFuzzyCharDic;
456   end;
457
458 {-=========================== TREParseTree Class ===============================-}
459 {**************************************************************************
460 \81\9c  \8d\\95\96Ø\82ð\8aÇ\97\9d\82·\82é\83N\83\89\83X TREParseTree
461
462 \93Á\92¥\81F  \92\86\8aÔ\90ß(Internal node)\82Æ\97t(Leaf)\82ð\8dì\82é\82Æ\82«\82Í\81A\82»\82ê\82¼\82êMakeInternalNode
463         \83\81\83\\83b\83h\82ÆMakeLeaf\83\81\83\\83b\83h\82ð\8eg\82¤\81B
464         \82Ü\82½\81A\8d\\95\96Ø\82Æ\82Í\95Ê\82É\81AFNodeList\82ÆFLeafList\82©\82ç\92\86\8aÔ\90ß\82Æ\97t\82Ö\83\8a\83\93\83N\82µ\82Ä
465         \82¨\82­\82±\82Æ\82É\82æ\82è\81A\93r\92\86\82Å\83G\83\89\81[\82ª\94­\90\82µ\82Ä\82à\95K\82¸\83\81\83\82\83\8a\82ð\8aJ\95ú\82·\82é\81B
466 **************************************************************************}
467   { TREParseTree\82Ì\90ß\82Ì\8eí\97Þ\82ð\95\\82·\8c^}
468   REOperation_t = (reop_Char,     { \95\8e\9a\82»\82Ì\82à\82Ì }
469           reop_LHead,   { \95\93ª }
470           reop_LTail,   { \95\94ö }
471           reop_Concat,  { XY }
472           reop_Union,   { X|Y}
473           reop_Closure, { X* }
474           reop_Empty);  { \8bó }
475
476   { RENode_t\82Ö\82Ì\83|\83C\83\93\83^\8c^}
477   REpNode_t = ^RENode_t;
478
479   { TREParseTree\82Ì\8eq\90ß\82Ö\82Ì\83|\83C\83\93\83^\8c^}
480   REChildren_t = record
481     pLeft: REpNode_t;
482     pRight: REpNode_t;
483   end;
484
485   { TREParseTree\82Ì\90ß}
486   RENode_t = record
487     Op: REOperation_t;
488     case Char of
489     #0: (CharClass: RECharClass_t);
490     #1: (Children: REChildren_t);
491   end;
492
493 {\81\9c \8d\\95\96Ø\82ð\8aÇ\97\9d\82·\82é\83N\83\89\83X}
494   TREParseTree = class
495   private
496     FpHeadNode: REpNode_t;{\8d\\95\96Ø\82Ì\92¸\93_\82É\82 \82é\90ß}
497     FNodeList: TList;   {\92\86\8aÔ\90ß\82Ì\83\8a\83X\83g\81B}
498     FLeafList: TList;   {\97t\82Ì\83\8a\83X\83g\81B}
499   public
500     constructor Create;
501     destructor Destroy; override;
502
503     {\8d\\95\96Ø\82Ì\93à\95\94\90ß\82ð\8dì\90¬\81B
504       op \82Í\83m\81[\83h\82ª\95\\82·\89\89\8eZ\81Aleft\82Í\8d\82Ì\8eq\81Aright\82Í\89E\82Ì\8eq }
505     function MakeInternalNode(TheOp: REOperation_t; pLeft, pRight: REpNode_t): REpNode_t;
506
507     {\8d\\95\96Ø\82Ì\97t\82ð\8dì\90¬\81B
508       aStartChar, aEndChar \82Å\83L\83\83\83\89\83N\83^\83N\83\89\83X\82ð\95\\82·}
509     function MakeLeaf(aStartChar, aEndChar: WChar_t): REpNode_t;
510
511     {\94C\88Ó\82Ì\88ê\95\8e\9a\82ð\95\\82·'.'\83\81\83^\83L\83\83\83\89\83N\83^\82É\91Î\89\9e\82·\82é\95\94\95ª\96Ø\82ð\8dì\82é\81B
512      \81¦CR LF\82ð\8f\9c\82­\91S\82Ä\82Ì\83L\83\83\83\89\83N\83^\82ð\95\\82·\97t\82ðreop_Union\91\80\8dì\82ð\95\\82·\92\86\8aÔ\90ß\82Å\8c\8b\82ñ\82¾\82à\82Ì}
513     function MakeAnyCharsNode: REpNode_t; virtual;
514
515     {\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\97t\82ð\8dì\90¬
516      \81¦ \97t\82ð\95Ô\82·\82ª\81AMakeInternalNode\82ð\8eg\82¤\81B}
517     function MakeLHeadNode(WChar: WChar_t): REpNode_t;
518
519     {\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\97t\82ð\8dì\90¬
520      \81¦ \97t\82ð\95Ô\82·\82ª\81AMakeInternalNode\82ð\8eg\82¤\81B}
521     function MakeLTailNode(WChar: WChar_t): REpNode_t;
522
523     {\88ø\90\94\82ª aStartChar <= aEndChar \82Ì\8aÖ\8cW\82ð\96\9e\82½\82µ\82Ä\82¢\82é\82Æ\82«\82É\81AMakeLeaf\82ð\8cÄ\82Ô
524      \82»\82ê\88È\8aO\82Í\81Anil \82ð\95Ô\82·\81B}
525     function Check_and_MakeLeaf(aStartChar, aEndChar: WChar_t):REpNode_t;
526
527     {\97t\82ð\93à\95\94\90ß\82É\95Ï\82¦\82é\81B}
528     procedure ChangeLeaftoNode(pLeaf, pLeft, pRight: REpNode_t);
529
530     {\91S\82Ä\82Ì\97t\82ª\8e\9d\82Â\83L\83\83\83\89\83N\83^\83N\83\89\83X\82Ì\94Í\88Í\82ª\82»\82ê\82¼\82ê\8fd\95¡\82µ\82È\82¢\82æ\82¤\82É\95ª\8a\84\82·\82é\81B}
531     procedure ForceCharClassUnique;
532
533     {\82·\82×\82Ä\82Ì\90ß\81i\93à\95\94\90ß\81A\97t\81j\82ð\8dí\8f\9c\81B}
534     procedure DisposeTree;
535
536     {\8d\\95\96Ø\82Ì\92¸\93_\82É\82 \82é\90ß}
537     property pHeadNode: REpNode_t read FpHeadNode write FpHeadNode;
538
539     {\93à\95\94\90ß\82Ì\83\8a\83X\83g}
540     property NodeList: TList read FNodeList;
541     {\97t\82Ì\83\8a\83X\83g}
542     property LeafList: TList read FLeafList;
543   end;
544
545 {-=========================== TREParser Class ===============================-}
546 {\81\9c \90³\8bK\95\\8c»\95\8e\9a\97ñ\82ð\89ð\90Í\82µ\82Ä\8d\\95\96Ø\82É\82·\82é\83p\81[\83T\81[ }
547   TREParser = class
548   private
549     FParseTree: TREParseTree; {\83\86\83j\83b\83gParseTre.pas \82Å\92è\8b`\82³\82ê\82Ä\82¢\82é\8d\\95\96Ø\83N\83\89\83X}
550     FScanner: TREScanner;         {\83g\81[\83N\83\93\8aÇ\97\9d\83N\83\89\83X}
551
552   protected
553     { <regexp>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
554       \91I\91ð X|Y \82ð\89ð\90Í\82·\82é}
555     function Regexp: REpNode_t;
556
557     { <term>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
558       \98A\8c\8b\82w\82x\82ð\89ð\90Í\82·\82é}
559     function term: REpNode_t;
560
561     { <factor>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
562       \8cJ\82è\95Ô\82µX*, X+\82ð\89ð\90Í\82·\82é}
563     function factor: REpNode_t;
564
565     { <primary>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
566       \95\8e\9a\82»\82Ì\82à\82Ì\82Æ\81A\8a\87\8cÊ\82Å\8a\87\82ç\82ê\82½\90³\8bK\95\\8c» (X) \82ð\89ð\90Í\82·\82é}
567     function primary: REpNode_t;
568
569     { <charclass> \82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
570       [ abcd] \82Å\8a\87\82ç\82ê\82½\90³\8bK\95\\8c»\82ð\89ð\90Í\82·\82é}
571     function CharacterClass(aParseTree: TREParseTree): REpNode_t;
572
573     { <negative charclass>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
574       [^abcd] \82Å\8a\87\82ç\82ê\82½\90³\8bK\95\\8c»\82ð\89ð\90Í\82·\82é}
575     function NegativeCharacterClass: REpNode_t;
576
577   public
578     constructor Create(RegExpStr: String);
579     destructor Destroy; override;
580
581     {\90³\8bK\95\\8c»\82ð\83p\81[\83X\82·\82é\81B
582       regexp, term, factor, primary, charclass \82Ì\8ae\83\81\83\\83b\83h\82ð\8eg\82¢\8dÄ\8bA\89º\8d~\96@
583       \82É\82æ\82Á\82Ä\89ð\90Í\82·\82é\81B}
584     procedure Run;
585
586     {\8d\\95\96Ø\82ð\8aÇ\97\9d\82·\82é\83I\83u\83W\83F\83N\83g}
587     property ParseTree: TREParseTree read FParseTree;
588
589     {\93ü\97Í\95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82·\83I\83u\83W\83F\83N\83g}
590     property Scanner: TREScanner read FScanner;
591
592 {$IFDEF DEBUG}
593     {\83A\83E\83g\83\89\83C\83\93\81E\83R\83\93\83g\83\8d\81[\83\8b\82É\8d\\95\96Ø\82Ì\90}\82ð\8f\91\82«\8fo\82·\83\81\83\\83b\83h}
594     procedure WriteParseTreeToOutLine(anOutLine: TOutLine);
595 {$ENDIF}
596   end;
597
598 {$IFDEF DEBUG}
599   function DebugWCharToStr(WChar: WChar_t): String;
600 {$ENDIF}
601
602 { -============================== TRE_NFA Class ==================================-}
603 type
604   RE_pNFANode_t = ^RE_NFANode_t;
605
606   { NFA\8fó\91Ô\95\\82Ì\90ß
607     RE_NFANode_t \82Í 1\82Â\82Ì\82m\82e\82`\8fó\91Ô\82ª\81A\83L\83\83\83\89\83N\83^\83N\83\89\83X(CharClass)\93à\82Ì\95\8e\9a\82É\82æ\82Á
608     \82Ä\91J\88Ú\82·\82é\82m\82e\82`\8fó\91Ô\82Ì\8fó\91Ô\94Ô\8d\86(TransitTo)\82ð\8ai\94[\82·\82é\81B
609     \82P\82Â\82Ì\82m\82e\82`\8fó\91Ô\82Ö\93ü\97Í\82³\82ê\82é\83L\83\83\83\89\83N\83^\83N\83\89\83X\96\88\82É\83\8a\83\93\83N\81E\83\8a\83X\83g\82ð\8c`\90¬\82·\82é}
610   RE_NFANode_t = record
611     CharClass: RECharClass_t;{ \93ü\97Í : CharClass.StartChar \81` CharClass.EndChar}
612     TransitTo: integer;    { \91J\88Ú\90æ\81F FStateList\82Ì\83C\83\93\83f\83b\83N\83X}
613
614     Next: RE_pNFANode_t;      { \83\8a\83\93\83N\83\8a\83X\83g\82Ì\8e\9f\90ß}
615   end;
616
617 {\81\9c \8d\\95\96Ø\82ð\89ð\90Í\82µ\82ÄNFA\8fó\91Ô\95\\82ð\8dì\82é\83N\83\89\83X}
618   TRE_NFA = class
619   private
620     FStateList: TList;
621     FEntryState: Integer;
622     FExitState: Integer;
623     FParser: TREParser;
624     FRegExpHasLHead: Boolean;
625     FRegExpHasLTail: Boolean;
626     FLHeadWChar: WChar_t;
627     FLTailWChar: WChar_t;
628   protected
629     { \83m\81[\83h\82É\94Ô\8d\86\82ð\8a\84\82è\93\96\82Ä\82é}
630     function NumberNode: Integer;
631
632     { NFA\8fó\91Ô\90ß \82ð\82P\82Â\8dì\90¬}
633     function MakeNFANode: RE_pNFANode_t;
634
635     { FStateList\82É\8fó\91Ô\91J\88Ú\82ð\92Ç\89Á\82·\82é\81B
636       \8fó\91Ô TransFrom \82É\91Î\82µ\82Ä\81AChrClass\82Ì\82Æ\82«\82É\8fó\91Ô TransTo \82Ö\82Ì\91J\88Ú\82ð\92Ç\89Á\82·\82é\81B}
637     procedure AddTransition(TransFrom, TransTo: Integer; aCharClass: RECharClass_t);
638
639     { \8d\\95\96Ø pTree \82É\91Î\82·\82é StateList\82ð\90\90¬\82·\82é
640       NFA\82Ì\93ü\82è\8cû\82ðentry, \8fo\8cû\82ðway_out\82Æ\82·\82é }
641     procedure GenerateStateList(pTree: REpNode_t; entry, way_out: Integer);
642
643     { NFA\8fó\91Ô\95\\82ð\94j\8aü\82·\82é}
644     procedure DisposeStateList;
645
646   public
647     constructor Create(Parser: TREParser; LHeadWChar, LTailWChar: WChar_t);
648     destructor Destroy;override;
649
650     { \8d\\95\96Ø Tree\82É\91Î\89\9e\82·\82éNFA\82ð\90\90¬\82·\82é}
651     procedure Run;
652
653     {NFA \8fó\91Ô\82Ì\83\8a\83X\83g}
654     property StateList: TList read FStateList;
655
656     {NFA\82Ì\8f\89\8aú\8fó\91Ô\82ÌFStateList\82Ì\83C\83\93\83f\83b\83N\83X}
657     property EntryState: Integer read FEntryState;
658     {NFA\82Ì\8fI\97¹\8fó\91Ô\82ÌFStateList\82Ì\83C\83\93\83f\83b\83N\83X}
659     property ExitState: Integer read FExitState;
660
661     {\90³\8bK\95\\8c»\82ª\81A\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
662     property RegExpHasLHead: Boolean read FRegExpHasLHead;
663     {\90³\8bK\95\\8c»\82ª\81A\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
664     property RegExpHasLTail: Boolean read FRegExpHasLTail;
665
666     {\95\93ª\82ð\95\\82·\83\81\83^\83L\83\83\83\89\83N\83^ '^'\82É\97^\82¦\82é\83\86\83j\81[\83N\82È\83L\83\83\83\89\83N\83^\83R\81[\83h}
667     property LHeadWChar: WChar_t read FLHeadWChar write FLHeadWChar;
668     {\95\94ö\82ð\95\\82·\83\81\83^\83L\83\83\83\89\83N\83^ '$'\82É\97^\82¦\82é\83\86\83j\81[\83N\82È\83L\83\83\83\89\83N\83^\83R\81[\83h}
669     property LTailWChar: WChar_t read FLTailWChar write FLTailWChar;
670
671 {$IFDEF DEBUG}
672     {TStrings\83I\83u\83W\83F\83N\83g\82É\81ANFA \82Ì\93à\97e\82ð\8f\91\82«\8d\9e\82Þ}
673     procedure WriteNFAtoStrings(Strings: TStrings);
674 {$ENDIF}
675   end;
676
677 { -========================== TRE_NFAStateSet Class =============================-}
678 {\81\9c NFA\82Ì\8fó\91Ô\8fW\8d\87\82ð\95\\82·\83I\83u\83W\83F\83N\83g
679     \93à\95\94\82Å\82Í\83r\83b\83g\83x\83N\83^\82Å\8fó\91Ô\8fW\8d\87\82ð\8eÀ\8c»\82µ\82Ä\82¢\82é\81B}
680   TRE_NFAStateSet = class
681   private
682     FpArray: PByteArray;
683     FCapacity: Integer;
684   public
685     {\83R\83\93\83X\83g\83\89\83N\83^\82É\82Í\81A\8dÅ\91å\8fó\91Ô\90\94\82ð\8ew\92è\82·\82é\81B}
686     constructor Create(StateMax: Integer);
687     destructor Destroy; override;
688
689     {\83I\83u\83W\83F\83N\83g\82Ì\8fW\8d\87\82ª\81AStateIndex\82ð\8aÜ\82Þ\82©\81H}
690     function Has(StateIndex: Integer): Boolean;
691     {\83I\83u\83W\83F\83N\83g\82Ì\8fW\8d\87\82ª\81AAStateSet\82Æ\93¯\82\8fW\8d\87\8fó\91Ô\82©\81H}
692     function Equals(AStateSet: TRE_NFAStateSet): Boolean;
693     {\83I\83u\83W\83F\83N\83g\82Ì\8fW\8d\87\82ÉStateIndex\82ð\8aÜ\82ß\82é\81B}
694     procedure Include(StateIndex: Integer);
695     {\83I\83u\83W\83F\83N\83g\82ª\8e\9d\82Â\83o\83C\83g\94z\97ñ\82Ö\82Ì\83|\83C\83\93\83^}
696     property pArray: PByteArray read FpArray;
697     {\83I\83u\83W\83F\83N\83g\82ª\8e\9d\82Â\83o\83C\83g\94z\97ñ\82Ì\97v\91f\90\94}
698     property Capacity: Integer read FCapacity;
699   end;
700
701 { -============================= TRE_DFA Class ==================================-}
702 {\81\9c TRE_DFA           NFA\8fó\91Ô\95\\82©\82çDFA\8fó\91Ô\95\\82ð\8dì\82é\83N\83\89\83X
703   \83R\83\93\83X\83g\83\89\83N\83^ Create \82É\81A\90³\8bK\95\\8c»\82ð\95\\82·\82m\82e\82`(\94ñ\8c\88\92è\90«\97L\8cÀ\83I\81[\83g\83}\83g\83\93
704   Non-deterministic Finite Automaton)\82Ì\8fó\91Ô\95\\82ð\8e\9d\82ÂTRE_NFA\82ð\8eó\82¯\8eæ\82è\81A
705   \91Î\89\9e\82·\82é\82c\82e\82`(\8c\88\92è\90«\97L\8cÀ\83I\81[\83g\83}\83g\83\93Deterministic Finite Automaton)
706   \82Ì\8fó\91Ô\83\8a\83X\83g\83I\83u\83W\83F\83N\83g\82ð\8d\\92z\82·\82éTRE_DFA\83N\83\89\83X\81B}
707
708   RE_pDFATransNode_t = ^RE_DFATransNode_t;
709
710   {TRE_DFA\82Ì\83\81\83\\83b\83hCompute_Reachable_N_state(DState: PD_state_t): RE_pDFATransNode_t;
711   \82ª\82±\82Ì\8c^\82Ì\92l\82ð\95Ô\82·\81B
712   \83L\83\83\83\89\83N\83^\83N\83\89\83X(CharClass)\82Å\91J\88Ú\89Â\94\\82È\82m\82e\82`\8fó\91Ô\8fW\8d\87(ToNFAStateSet)}
713   RE_DFATransNode_t = record
714     CharClass: RECharClass_t;{Char;}
715     ToNFAStateSet: TRE_NFAStateSet;
716
717     next: RE_pDFATransNode_t;{\83\8a\83\93\83N\83\8a\83X\83g\82ð\8c`\90¬}
718   end;
719
720   RE_pDFAStateSub_t = ^RE_DFAStateSub_t;
721   RE_pDFAState_t = ^RE_DFAState_t;
722
723   { RE_DFAState_t\82É\82æ\82Á\82Ä\8eg\97p\82³\82ê\82é
724   \83L\83\83\83\89\83N\83^\83N\83\89\83X(CharClass)\82É\82æ\82Á\82ÄDFA\8fó\91Ô(TransitTo) \82Ö\91J\88Ú\82·\82é\81B}
725   RE_DFAStateSub_t = record
726     CharClass: RECharClass_t;
727     TransitTo: RE_pDFAState_t; {CharClass\94Í\88Í\93à\82Ì\95\8e\9a\82Å DFA \8fó\91Ô TransitTo\82Ö}
728
729     next: RE_pDFAStateSub_t; {\83\8a\83\93\83N\83\8a\83X\83g\82Ì\8e\9f\82Ì\83f\81[\83^}
730   end;
731
732   { RE_DFAState_t\82Í\82c\82e\82`\8fó\91Ô\82ð\95\\82·\8c^}
733   RE_DFAState_t = record
734     StateSet: TRE_NFAStateSet; {\82±\82ÌDFA\8fó\91Ô\82ð\95\\82·NFA\8fó\91Ô\8fW\8d\87}
735     Visited: wordbool; { \8f\88\97\9d\8dÏ\82Ý\82È\82ç\82P}
736     Accepted: wordbool;{ StateSet\83t\83B\81[\83\8b\83h\82ªNFA\82Ì\8fI\97¹\8fó\91Ô\82ð\8aÜ\82Þ\82È\82ç\82P}
737     Next: RE_pDFAStateSub_t;  { \83L\83\83\83\89\83N\83^\83N\83\89\83X\96\88\82Ì\91J\88Ú\90æ\82Ì\83\8a\83\93\83N\83\8a\83X\83g}
738   end;
739
740\81\9c NFA\8fó\91Ô\95\\82©\82çDFA\8fó\91Ô\95\\82ð\8dì\82é\83N\83\89\83X}
741   TRE_DFA = class
742   private
743     FStateList: TList;
744     FpInitialState: RE_pDFAState_t;
745     FNFA: TRE_NFA;
746
747     FRegExpIsSimple: Boolean;
748     FSimpleRegExpStr: String;
749     FRegExpHasLHead: Boolean;
750     FRegExpHasLTail: Boolean;
751   protected
752     { NFA\8fó\91Ô\8fW\8d\87 StateSet \82É\91Î\82µ\82Ä \83Ã-closure\91\80\8dì\82ð\8eÀ\8ds\82·\82é\81B
753     \83Ã\91J\88Ú\82Å\91J\88Ú\89Â\94\\82È\91S\82Ä\82Ì\82m\82e\82`\8fó\91Ô\82ð\92Ç\89Á\82·\82é}
754     procedure Collect_Empty_Transition(StateSet: TRE_NFAStateSet);
755
756     { NFA\8fó\91Ô\8fW\8d\87 aStateSet \82ð\82c\82e\82`\82É\93o\98^\82µ\82Ä\81A\82c\82e\82`\8fó\91Ô\82Ö\82Ì\83|\83C\83\93\83^\82ð\95Ô\82·\81B
757       aStateSet\82ª\8fI\97¹\8fó\91Ô\82ð\8aÜ\82ñ\82Å\82¢\82ê\82Î\81Aaccepted\83t\83\89\83O\82ð\83Z\83b\83g\82·\82é\81B
758       \82·\82Å\82ÉaStateSet\82ª\82c\82e\82`\82É\93o\98^\82³\82ê\82Ä\82¢\82½\82ç\89½\82à\82µ\82È\82¢}
759     function Register_DFA_State(var aStateSet: TRE_NFAStateSet): RE_pDFAState_t;
760
761     { \8f\88\97\9d\8dÏ\82Ý\82Ì\88ó\82ª\82Â\82¢\82Ä\82¢\82È\82¢\82c\82e\82`\8fó\91Ô\82ð\92T\82·\81B
762       \8c©\82Â\82©\82ç\82È\82¯\82ê\82Înil\82ð\95Ô\82·\81B}
763     function Fetch_Unvisited_D_state: RE_pDFAState_t;
764
765     { DFA\8fó\91ÔpDFAState\82©\82ç\91J\88Ú\89Â\94\\82ÈNFA\8fó\91Ô\82ð\92T\82µ\82Ä\81A\83\8a\83X\83g\82É\82µ\82Ä\95Ô\82·}
766     function Compute_Reachable_N_state(pDFAState: RE_pDFAState_t): RE_pDFATransNode_t;
767
768     { Compute_Reachable_N_state\83\81\83\\83b\83h\82©\8dì\82é RE_DFATransNode_t\8c^\82Ì\83\8a\83\93\83N\83\8a\83X\83g\82ð
769     \94p\8aü\82·\82é}
770     procedure Destroy_DFA_TransList(pDFA_TransNode: RE_pDFATransNode_t);
771
772     { NFA\82ð\93\99\89¿\82È\82c\82e\82`\82Ö\82Æ\95Ï\8a·\82·\82é}
773     procedure Convert_NFA_to_DFA;
774
775     { StateList\82Ì\8ae\83\8a\83\93\83N\83\8a\83X\83g\82ð\83\\81[\83g\82·\82é}
776     procedure StateListSort;
777
778     procedure CheckIfRegExpIsSimple;
779     procedure DestroyStateList;
780   public
781     constructor Create(NFA: TRE_NFA);
782     destructor Destroy; override;
783
784     procedure Run;
785
786     property StateList: TList read FStateList;
787
788     property pInitialState: RE_pDFAState_t read FpInitialState;
789
790     {\90³\8bK\95\\8c»\82ª\92P\8f\83\82È\95\8e\9a\97ñ\82©\81H}
791     property RegExpIsSimple: Boolean read FRegExpIsSimple;
792     {\90³\8bK\95\\8c»\82Æ\93\99\89¿\82È\92P\8f\83\82È\95\8e\9a\97ñ}
793     property SimpleRegExpStr: String read FSimpleRegExpStr;
794
795     {\90³\8bK\95\\8c»\82ª\81A\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
796     property RegExpHasLHead: Boolean read FRegExpHasLHead;
797     {\90³\8bK\95\\8c»\82ª\81A\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
798     property RegExpHasLTail: Boolean read FRegExpHasLTail;
799   {$IFDEF DEBUG}
800     {TStrings\83I\83u\83W\83F\83N\83g\82É\81ADFA \82Ì\93à\97e\82ð\8f\91\82«\8d\9e\82Þ}
801     procedure WriteDFAtoStrings(Strings: TStrings);
802 {$ENDIF}
803   end;
804
805 { -=================== TRegularExpression Class ==============================-}
806   {TStringList \82É\8ai\94[\82Å\82«\82é\8d\80\96Ú\90\94\82Ì\94Í\88Í\8c^}
807   RE_IndexRange_t = 1..Classes.MaxListSize;
808
809 {\81\9c \90³\8bK\95\\8c»\95\8e\9a\97ñ\82©\82ç\82c\82e\82`\8fó\91Ô\95\\82ð\8dì\82é\83N\83\89\83X}
810   TRegularExpression = class(TComponent)
811   private
812   protected
813     FLineHeadWChar: WChar_t;
814     FLineTailWChar: WChar_t;
815     {\83v\83\8a\83v\83\8d\83Z\83b\83T\82ð\92Ê\82é\91O\82Ì\90³\8bK\95\\8c»}
816     FRegExp: String;
817     {\90³\8bK\95\\8c»\82Ì\95\8e\9a\97ñ\83\8a\83X\83g\81BObjects\83v\83\8d\83p\83e\83B\82ÉT\82c\82e\82`\83I\83u\83W\83F\83N\83g\82ð\8e\9d\82Â}
818     FRegExpList: TStringList;
819     {FRegExpList\82É\8ai\94[\82·\82é\8d\80\96Ú\90\94\82Ì\8dÅ\91å\92l\81\83f\83t\83H\83\8b\83g 30}
820     FRegExpListMax: RE_IndexRange_t;
821     {\8c»\8dÝ\8ew\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c» RegExp\82Ì\90³\8bK\95\\8c»\95\8e\9a\97ñ\83\8a\83X\83gRegExpList\92\86\82Å\82Ì
822      \83C\83\93\83f\83b\83N\83X
823      \81¦ FRegExpList[FCurrentIndex] = RegExp}
824     FCurrentIndex: Integer;
825     {\93¯\88Ó\8cê\8f\88\97\9d\83v\83\8a\83v\83\8d\83Z\83b\83T}
826     FPreProcessor: TREPreProcessor;
827
828   { \93à\95\94\8eg\97p\82Ì\82½\82ß\82Ì\8eè\91±\82«\81E\8aÖ\90\94}
829     {*****     \90³\8bK\95\\8c»\95\8e\9a\97ñ\81¨\8d\\95\96Ø\8d\\91¢\81¨NFA\81¨DFA \82Ì\95Ï\8a·\82ð\8ds\82¤ *****}
830     procedure Translate(RegExpStr: String); virtual;
831
832     {\90³\8bK\95\\8c»\83\8a\83X\83g(RegExpList: TStringList)\82ÆObjects\83v\83\8d\83p\83e\83B\82É\8c\8b\82Ñ\95t\82¯\82ç\82ê\82½
833      TRE_DFA\83I\83u\83W\83F\83N\83g\82ð\94j\8aü}
834     procedure DisposeRegExpList;
835
836   {\83v\83\8d\83p\83e\83B\81E\83A\83N\83Z\83X\81E\83\81\83\\83b\83h}
837     procedure SetRegExp(Str: String); virtual;
838     function  GetProcessedRegExp: String;
839     function  GetListOfFuzzyCharDic: TList;
840     function  GetListOfSynonymDic: TList;
841     function  GetRegExpIsSimple: Boolean;
842     function  GetSimpleRegExp: String;
843     function  GetHasLHead: Boolean;
844     function  GetHasLTail: Boolean;
845     function  GetUseFuzzyCharDic: Boolean;
846     procedure SetUseFuzzyCharDic(Val: Boolean);
847     function  GetUseSynonymDic: Boolean;
848     procedure SetUseSynonymDic(Val: Boolean);
849     function  GetLineHeadWChar: WChar_t; virtual;
850     function  GetLineTailWChar: WChar_t; virtual;
851   {DFA\83I\83u\83W\83F\83N\83g\8aÖ\98A\83\81\83\\83b\83h}
852     {\8c»\8dÝ\8ew\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c»\82É\91Î\89\9e\82·\82é\82c\82e\82`\8fó\91Ô\95\\82Ì\8f\89\8aú\8fó\91Ô\82Ö\82Ì\83|\83C\83\93\83^\82ð\95Ô\82·}
853     function GetpInitialDFAState: RE_pDFAState_t;
854     {\8c»\8dÝ\8ew\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c»\82É\91Î\89\9e\82·\82éTRE_DFA\83I\83u\83W\83F\83N\83g\82ð\95Ô\82·}
855     function GetCurrentDFA: TRE_DFA;
856     {\8fó\91Ô DFAstate\82©\82ç\95\8e\9a\82\83\82É\82æ\82Á\82Ä\91J\88Ú\82µ\82Ä\81A\91J\88Ú\8cã\82Ì\8fó\91Ô\82ð\95Ô\82·\81B
857      \95\8e\9a\82\83\82É\82æ\82Á\82Ä\91J\88Ú\8fo\97\88\82È\82¯\82ê\82Înil\82ð\95Ô\82·}
858     function NextDFAState(DFAState: RE_pDFAState_t; c: WChar_t): RE_pDFAState_t;
859     {DFA\8fó\91Ô\95\\82Ì\92\86\82Å\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\83L\83\83\83\89\83N\83^\83R\81[\83h}
860     property LineHeadWChar: WChar_t read GetLineHeadWChar;
861     {DFA\8fó\91Ô\95\\82Ì\92\86\82Å\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\83L\83\83\83\89\83N\83^\83R\81[\83h}
862     property LineTailWChar: WChar_t read GetLineTailWChar;
863
864   {\90³\8bK\95\\8c»\8aÖ\98A\83v\83\8d\83p\83e\83B}
865     {\8c»\8dÝ\8ew\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c»}
866     property RegExp: String read FRegExp write SetRegExp;
867
868     {\8c»\8dÝ\8ew\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c»\82É\93¯\88Ó\8cê\8f\88\97\9d\82ð\8e{\82µ\82½\82à\82Ì}
869     property ProcessedRegExp: String read GetProcessedRegExp;
870
871     {\90³\8bK\95\\8c»\82ª\92P\8f\83\82È\95\8e\9a\97ñ\82©\81H}
872     property RegExpIsSimple: Boolean read GetRegExpIsSimple;
873     {\90³\8bK\95\\8c»\82Æ\93\99\89¿\82È\92P\8f\83\82È\95\8e\9a\97ñ(\81¦RegExpIsSimple=False\82Ì\8e\9e\82Í\83k\83\8b\95\8e\9a\97ñ)}
874     property SimpleRegExp: String read GetSimpleRegExp;
875
876     {\90³\8bK\95\\8c»\82ª\81A\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
877     property HasLHead: Boolean read GetHasLHead;
878     {\90³\8bK\95\\8c»\82ª\81A\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
879     property HasLTail: Boolean read GetHasLTail;
880
881   {\8e«\8f\91\8aÖ\98A\83v\83\8d\83p\83e\83B}
882     {\95\8e\9a\93¯\88ê\8e\8b\8e«\8f\91\82ð\8eg\82¤\81^\8eg\82í\82È\82¢\8ew\92è}
883     property UseFuzzyCharDic: Boolean read GetUseFuzzyCharDic write SetUseFuzzyCharDic;
884     {\95\8e\9a\82Ì\93¯\88ê\8e\8b\8e«\8f\91\82Ì\83\8a\83X\83g}
885     property ListOfFuzzyCharDic: TList read GetListOfFuzzyCharDic;
886
887     {\93¯\88Ó\8cê\8e«\8f\91\82ð\8eg\82¤\81^\8eg\82í\82È\82¢\8ew\92è}
888     property UseSynonymDic: Boolean read GetUseSynonymDic write SetUseSynonymDic;
889     {\93¯\88Ó\8cê\8e«\8f\91\82Ì\83\8a\83X\83g}
890     property ListOfSynonymDic: TList read GetListOfSynonymDic;
891   public
892     constructor Create(AOwner: TComponent); override;
893     destructor Destroy; override;
894   end;
895
896 { -========================== TAWKStr Class ==================================-}
897   TMatchCORE_LineSeparator = (mcls_CRLF, mcls_LF);
898
899   TMatchCORE = class(TRegularExpression)
900   private
901     FLineSeparator: TMatchCORE_LineSeparator;
902   protected
903     function IsLineEnd(WChar: WChar_t): Boolean;
904     property LineSeparator: TMatchCORE_LineSeparator
905       read FLineSeparator write FLineSeparator;
906   protected
907
908     {\90à\96¾ \81F    \83}\83b\83`
909                 (\90³\8bK\95\\8c»\82ª\8ds\93ª\81^\8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Ü\82È\82¢\82Æ\82«\97p)
910     \93®\8dì  \81F
911     \88ø\90\94  \81F    pText: PChar    \83k\83\8b\83L\83\83\83\89\83N\83^\82Å\8fI\82í\82é\8c\9f\8dõ\91Î\8fÛ\95\8e\9a\97ñ\82Ö\82Ì\83|\83C\83\93\83^
912     \95\9b\8dì\97p\81F    pStart:PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\90æ\93ª\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
913                 pEnd  :PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\8e\9f\82Ì\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
914     \92\8d\88Ó  \81F    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\83o\83C\83g\90\94\82Í\81ApEnd - pStart\82Å\93¾\82ç\82ê\82é\81B}
915     procedure MatchStd(pText: PChar; var pStart, pEnd: PChar);
916
917
918     {\90à\96¾ \81F    \83}\83b\83`(\90³\8bK\95\\8c»\82ª\8ds\93ª\81^\8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82Æ\82«\97p)
919     \93®\8dì  \81F
920     \88ø\90\94  \81F    pText: PChar    \83k\83\8b\83L\83\83\83\89\83N\83^\82Å\8fI\82í\82é\8c\9f\8dõ\91Î\8fÛ\95\8e\9a\97ñ\82Ö\82Ì\83|\83C\83\93\83^
921     \95\9b\8dì\97p\81F    pStart:PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\90æ\93ª\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
922                 pEnd  :PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\8e\9f\82Ì\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
923     \92\8d\88Ó  \81F    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\83o\83C\83g\90\94\82Í\81ApEnd - pStart\82Å\93¾\82ç\82ê\82é\81B}
924     procedure MatchEX(pText: PChar; var pStart, pEnd: PChar);
925
926     {\90à\96¾ \81F    \83}\83b\83`(\93à\95\94\8f\88\97\9d\97p\81B\90³\8bK\95\\8c»\82ª\8ds\93ª\81^\8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82Æ\82«\97p)
927     \93®\8dì  \81F    MatchEx_Head\83\81\83\\83b\83h\82Æ\82Ì\88á\82¢\82Í\81A\88ø\90\94pText\82ª\8ds\82Ì\93r\92\86\82ð\83|\83C\83\93\83g\82µ\82Ä
928                 \82¢\82é\82à\82Ì\82Æ\82µ\82Ä\81A\8ds\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82É\83}\83b\83`\82µ\82È\82¢\82±\82Æ\81B
929     \88ø\90\94  \81F    pText: PChar    \83k\83\8b\83L\83\83\83\89\83N\83^\82Å\8fI\82í\82é\8c\9f\8dõ\91Î\8fÛ\95\8e\9a\97ñ\82Ö\82Ì\83|\83C\83\93\83^
930                                 (\8ds\82Ì\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82à\82Ì\82Æ\82µ\82Ä\88µ\82¤\81B)
931     \95\9b\8dì\97p\81F    pStart:PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\90æ\93ª\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
932                 pEnd  :PChar    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\8e\9f\82Ì\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^
933     \92\8d\88Ó  \81F    \83}\83b\83`\82µ\82½\95\94\95ª\82Ì\83o\83C\83g\90\94\82Í\81ApEnd - pStart\82Å\93¾\82ç\82ê\82é\81B}
934     procedure MatchEX_Inside(pText: PChar; var pStart, pEnd: PChar);
935
936 {----------------\83}\83b\83\89º\90¿\82¯    -------------}
937 {MatchHead, MatchInside\82Í\81A\88ø\90\94 pText\82ª\8ew\82·\95\8e\9a\82ð\90æ\93ª\82Æ\82µ\82Ä\83}\83b\83`\82·\82é\82©\82ð\8c\9f\8d¸\82·\82é}
938
939     {\90à\96¾ \81F    pText\82Í\81A\82 \82é\95\8e\9a\97ñ\82Ì\8ds\93ª\82ð\83|\83C\83\93\83g\82µ\82Ä\82¢\82é\82à\82Ì\82Æ\8c©\82È\82·\81B
940                 \82µ\82½\82ª\82Á\82Ä\81ApText\82ª\8ew\82·\95\8e\9a\82Í\8ds\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82É\83}\83b\83`\82·\82é\81B
941                 \8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8dl\97\82·\82é\81B
942     \88ø\90\94  \81F    pText: PChar      \8c\9f\8dõ\91Î\8fÛ\95\8e\9a\97ñ(\8ds\82Ì\8dÅ\8f\89\82Ì\95\8e\9a\82ð\8ew\82·)
943                 pDFAState         \8f\89\8aú\92l\82Æ\82µ\82Ä\8eg\82¤DFA\8fó\91Ô\95\\82Ì\82P\8fó\91Ô
944     \95Ô\82è\92l\81F    \83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ\82Ì\8e\9f\82Ì\95\8e\9a\81B
945                 \83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ\82Ì\83o\83C\83g\92·\82Í\81Aresult - pText
946     \92\8d\88Ó  \81F    }
947     function MatchHead(pText: PChar; pDFAState: RE_pDFAState_t): PChar;
948
949     {\90à\96¾ \81F    pText\82Í\81A\82 \82é\95\8e\9a\97ñ\82Ì\92\86(\8ds\93ª\82Å\82Í\82È\82¢)\82ð\83|\83C\83\93\83g\82µ\82Ä\82¢\82é\82à\82Ì\82Æ\8c©\82È\82·\81B
950                 \82µ\82½\82ª\82Á\82Ä\81ApText\82ª\8ew\82·\95\8e\9a\82Í\8ds\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82É\83}\83b\83`\82µ\82È\82¢\81B
951                 \8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8dl\97\82·\82é\81B
952     \88ø\90\94  \81F    pText: PChar      \8c\9f\8dõ\91Î\8fÛ\95\8e\9a\97ñ(\8ds\92\86\82Ì\95\8e\9a\82ð\8ew\82·)
953                 pDFAState         \8f\89\8aú\92l\82Æ\82µ\82Ä\8eg\82¤DFA\8fó\91Ô\95\\82Ì\82P\8fó\91Ô
954     \95Ô\82è\92l\81F    \83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ\82Ì\8e\9f\82Ì\95\8e\9a\81B
955                 \83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ\82Ì\83o\83C\83g\92·\82Í\81Aresult - pText
956     \92\8d\88Ó  \81F    }
957     function MatchInside(pText: PChar; pDFAState: RE_pDFAState_t): PChar;
958   public
959     constructor Create(AOwner: TComponent); override;
960   end;
961
962 { -========================== TAWKStr Class ==================================-}
963   TAWKStrMatchProc = procedure(pText: PChar; var pStart, pEnd: PChar) of object;
964
965 {\81\9c AWK\8c¾\8cê\82Ì\95\8e\9a\97ñ\91\80\8dì\8aÖ\90\94\8cQ\82ðDelphi\82Å\8eÀ\8c»\82·\82é\83N\83\89\83X TAWKStr}
966   TAWKStr = class(TMatchCORE)
967   private
968     FMatchProc: TAWKStrMatchProc;
969   protected
970     procedure SetRegExp(Str: String); override;
971     {Sub, GSub\83\81\83\\83b\83h\82Å\8eg\97p\81B '&'\82ð\83}\83b\83`\82µ\82½\95\8e\9a\97ñ\82É\92u\8a·\82¦\82é}
972     function Substitute_MatchStr_For_ANDChar(Text: String; MatchStr: String): String;
973   public
974     constructor Create(AOwner: TComponent); override;
975     function ProcessEscSeq(Text: String): String;
976
977     {\95\8e\9a\82Ì\93¯\88ê\8e\8b\8e«\8f\91\82Ì\83\8a\83X\83g}
978     property ListOfFuzzyCharDic;
979     {\93¯\88Ó\8cê\8e«\8f\91\82Ì\83\8a\83X\83g}
980     property ListOfSynonymDic;
981
982     {\90³\8bK\95\\8c»\82ª\81A\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
983     property HasLHead;
984     {\90³\8bK\95\\8c»\82ª\81A\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
985     property HasLTail;
986
987     property ProcessedRegExp;
988
989     {DFA\8fó\91Ô\95\\82Ì\92\86\82Å\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\83L\83\83\83\89\83N\83^\83R\81[\83h}
990     property LineHeadWChar;
991     {DFA\8fó\91Ô\95\\82Ì\92\86\82Å\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\83L\83\83\83\89\83N\83^\83R\81[\83h}
992     property LineTailWChar;
993
994     function Match(Text: String; var RStart, RLength: Integer): Integer;
995
996     function Sub(SubText: String; var Text: String): Boolean;
997
998     function GSub(SubText: String; var Text: String): Integer;
999
1000     function Split(Text: String; StrList: TStrings): Integer;
1001   published
1002     property RegExp;
1003     {\8ds\82Ì\8bæ\90Ø\82è\95\8e\9a\8ew\92è}
1004     property LineSeparator;
1005
1006     {\95\8e\9a\82Ì\93¯\88ê\8e\8b\8e«\8f\91\82ð\8eg\82¤\82©}
1007     property UseFuzzyCharDic;
1008     {\93¯\88Ó\8cê\8e«\8f\91\82ð\8eg\82¤\82©}
1009     property UseSynonymDic;
1010
1011   end;
1012
1013 { -========================== \97á\8aO\83N\83\89\83X =====================================-}
1014   EEndOfFile = class(EInOutError);
1015
1016   EFileNotFound = class(EInOutError);
1017
1018   EGrepCancel = class(Exception);
1019
1020 { -=========================== TTxtFile Class ================================-}
1021   {TTextFile\83N\83\89\83X\82ÌGetThisLine\82ª\95Ô\82·\83t\83@\83C\83\8b\92\86\82Ì\82P\8ds\82Ì\8fî\95ñ\82ð\95\\82·\8c^}
1022   RE_LineInfo_t = record
1023     Line: String;
1024     LineNo: Integer; {\8ds\94Ô\8d\86}
1025   end;
1026
1027 {\81\9c TTxtFile \83e\83L\83X\83g\83t\83@\83C\83\8b\81E\83A\83N\83Z\83X\81E\83N\83\89\83X}
1028   TTxtFile = Class
1029   private
1030   protected
1031   public
1032     FBuffSize: Integer; {\83o\83b\83t\83@\82Ì\83T\83C\83Y}
1033     FTailMargin: Integer;
1034     FpBuff: PChar;      {\93Ç\82Ý\8d\9e\82Ý\83o\83b\83t\83@\82Ö\82Ì\83|\83C\83\93\83^}
1035
1036     FFileName: String;  {\8f\88\97\9d\91Î\8fÛ\83t\83@\83C\83\8b\96¼ \81i\83t\83\8b\83p\83X\95\\8bL\81j}
1037     FF: File;           {FFileName \82É\8aÖ\98A\95t\82¯\82ç\82ê\82é\8c^\82È\82µ\83t\83@\83C\83\8b\95Ï\90\94}
1038     FFileOpened: Boolean;
1039
1040     {\83o\83b\83t\83@\92\86\82Ì\95\8e\9a\88Ê\92u\82ð\95\\82·\8fd\97v\82È\83|\83C\83\93\83^\82R\8eí\97Þ}
1041     FpBase: PChar;      {\95\92\86\82Å\8c\9f\8dõ\91Î\8fÛ\82Æ\82È\82é\95\94\95ª\95\8e\9a\97ñ\82Ì\90æ\93ª\82ð\8ew\82·}
1042     FpLineBegin: PChar; {FpBase\82ª\8ew\82·\95\82Ì\90æ\93ª\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^}
1043     FpForward: PChar;     {\8c\9f\8dõ\92\86\82Ì\95\8e\9a\82Ö\82Ì\83|\83C\83\93\83^}
1044
1045     FLineNo: Integer;   {\8c»\8dÝ\82Ì\8ds\94Ô\8d\86}
1046     FReadCount: Integer;{BlockRead \82Å\89½\83o\83C\83g\93Ç\82Ý\8d\9e\82ñ\82¾\82©\81B}
1047     FBrokenLine: String;{\83o\83b\83t\83@\82Ì\8b«\8aE\82Å\95ª\92f\82³\82ê\82½\95\82Ì\91O\94¼\95\94\95ª}
1048
1049     FpCancelRequest: ^Boolean;
1050     {IncPBase\83\81\83\\83b\83h\82ÅFpBase\82ª\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82ð\8ew\82µ\82½\82Æ\82«\82Ì\8f\88\97\9d}
1051     procedure IncPBaseNullChar(Ch: Char);
1052     {GetChar\83\81\83\\83b\83h\82ÅFpForward\82ª\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82ð\8ew\82µ\82½\82Æ\82«\82Ì\8f\88\97\9d}
1053     procedure GetCharNullChar(Ch: Char);
1054
1055     constructor Create(aFileName: String; var CancelRequest: Boolean);
1056     destructor Destroy; override;
1057     procedure BuffRead(pBuff: PChar);
1058     function IncPBase: Char;  {FpBase\82ª\8e\9f\82Ì\83o\83C\83g\82ð\8ew\82·\82æ\82¤\82É\82·\82é}
1059     function AdvanceBase: WChar_t;
1060     function GetChar: Char;
1061     function GetWChar: WChar_t;
1062     function GetThisLine: RE_LineInfo_t;{FpBase\82ª\8ew\82µ\82Ä\82¢\82é\95\8e\9a\82ð\8aÜ\82Þ\95\82ð\93¾\82é}
1063   end;
1064
1065 { -=========================== TGrep Class ==================================-}
1066
1067   TGrepOnMatch = procedure (Sender: TObject; LineInfo: RE_LineInfo_t) of Object;
1068
1069   TGrepGrepProc = procedure (FileName: String) of Object;
1070
1071 {\81\9c \83t\83@\83C\83\8b\90³\8bK\95\\8c»\8c\9f\8dõ\83N\83\89\83X TGrep }
1072   TGrep = class(TRegularExpression)
1073   private
1074     FOnMatch: TGrepOnMatch;
1075 //    FDummyIgnoreCase: Boolean;
1076     FCancel:  Boolean;
1077     FGrepProc: TGrepGrepProc;
1078   protected
1079     procedure SetRegExp(Str: String); override;
1080     function  GetLineHeadWChar: WChar_t; override;
1081     function  GetLineTailWChar: WChar_t; override;
1082   public
1083     constructor Create(AOwner: TComponent); override;
1084
1085     procedure GrepByRegExp(FileName: String);
1086     procedure GrepByStr(FileName: String);
1087
1088     {\8b@\94\8ew\92è\82³\82ê\82½\83e\83L\83X\83g\81E\83t\83@\83C\83\8b\92\86\82Å\90³\8bK\95\\8c»(RegExp\83v\83\8d\83p\83e\83B)\82É\83}\83b\83`
1089           \82·\82é\8ds\82ð\92T\82µ\81A\8c©\82Â\82¯\82é\82½\82Ñ\82ÉOnMatch \83C\83x\83\93\83g\83n\83\93\83h\83\89\82ð\8cÄ\82Ñ\8fo\82µ\82Ü\82·\81B
1090
1091           (RegExp\83v\83\8d\83p\83e\83B\82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\90³\8bK\95\\8c»\82ð\8c\9f\8d¸\82µ\82Ä\81A\95\81\92Ê\82Ì\95\8e\9a\97ñ\82È\82ç\82Î
1092            GrepByStr\83\81\83\\83b\83h\81A\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82Æ\82«\82ÍGrepByRegExp\83\81\83\\83b\83h\82ð
1093            \8cÄ\82Ñ\8fo\82µ\82Ü\82·\81B)
1094           \81¦ OnMatch \83C\83x\83\93\83g\83n\83\93\83h\83\89\82ª\8ew\92è\82³\82ê\82Ä\82¢\82È\82¢\82Æ\82«\82Í\81A\89½\82à\82µ\82Ü\82¹\82ñ\81B
1095
1096      \88ø\90\94   FileNmae        \8c\9f\8dõ\91Î\8fÛ\82Ì\83e\83L\83X\83g\83t\83@\83C\83\8b\96¼(\83t\83\8b\83p\83X\8ew\92è)
1097             CancelRequest   \8c\9f\8dõ\82ð\93r\92\86\82Å\8e~\82ß\82½\82¢\82Æ\82«\82ÉTrue\82É\82·\82é\81B
1098             \81¦ Grep\83\81\83\\83b\83h\82Í\93à\95\94\82Å\81AApplication.ProcessMessages\82ð\8cÄ\82Ñ\8fo\82·
1099                \82Ì\82Å\81A\82»\82Ì\82Æ\82«\82É\81ACancelRequest\82ðTrue\82É\90Ý\92è\82·\82é\82±\82Æ\82ª\82Å\82«\82Ü\82·\81B}
1100
1101     {\90³\8bK\95\\8c»\82ª\92P\8f\83\82È\95\8e\9a\97ñ\82©\81H}
1102     property RegExpIsSimple;
1103     {\90³\8bK\95\\8c»\82Æ\93\99\89¿\82È\92P\8f\83\82È\95\8e\9a\97ñ(\81¦RegExpIsSimple=False\82Ì\8e\9e\82Í\83k\83\8b\95\8e\9a\97ñ)}
1104     property SimpleRegExp;
1105
1106     {\90³\8bK\95\\8c»\82ª\81A\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
1107     property HasLHead;
1108     {\90³\8bK\95\\8c»\82ª\81A\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82Þ\82©}
1109     property HasLTail;
1110
1111     {RegExp\83v\83\8d\83p\83e\83B\82Ì\90³\8bK\95\\8c»\82É\93¯\88Ó\8cê\8f\88\97\9d\82ð\8e{\82µ\82½\82à\82Ì}
1112     property ProcessedRegExp;
1113     {\95\8e\9a\82Ì\93¯\88ê\8e\8b\8e«\8f\91\82Ì\83\8a\83X\83g}
1114     property ListOfFuzzyCharDic;
1115     {\93¯\88Ó\8cê\8e«\8f\91\82Ì\83\8a\83X\83g}
1116     property ListOfSynonymDic;
1117
1118     property Grep: TGrepGrepProc read FGrepProc;
1119   published
1120     {\90³\8bK\95\\8c»\95\8e\9a\97ñ}
1121     property RegExp;
1122     {\95\8e\9a\82Ì\93¯\88ê\8e\8b\8e«\8f\91\82ð\8eg\82¤\82©}
1123     property UseFuzzyCharDic;
1124     {\93¯\88Ó\8cê\8e«\8f\91\82ð\8eg\82¤\82©}
1125     property UseSynonymDic;
1126
1127     property OnMatch: TGrepOnMatch read FOnMatch write FOnMatch;
1128
1129     property Cancel: Boolean read FCancel write FCancel;
1130   end;
1131
1132
1133
1134 var
1135   RE_FuzzyCharDic: TList;
1136
1137 procedure Register;
1138
1139 implementation
1140 {************************  Implementation ************************************}
1141 constructor ERegExpParser.Create(const Msg: string; ErrorPosition: Word);
1142 begin
1143   inherited Create(Msg);
1144   ErrorPos := ErrorPosition;
1145 end;
1146 { -====================== \95\8e\9a\97ñ\91\80\8dì\8aÖ\90\94 =====================================-}
1147 {\90à\96¾ \81F  \82P\82U\90i\90\94\82ð\95\\82·\95\8e\9a\82ð\8eó\82¯\8eæ\82è\81A\90®\90\94\82É\82µ\82Ä\95Ô\82·\81B
1148  \88ø\90\94 \81F  WCh: WChar_t;     16\90i\90\94\82ð\95\\82·1\83o\83C\83g\95\8e\9a [0-9a-fA-F]
1149
1150  \95Ô\82è\92l\81\90³\8fí\8e\9e\81F  0 <= result <= 15
1151           \88Ù\8fí\8e\9e\81F  -1}
1152 function HexWCharToInt(WCh: WChar_t): Integer;
1153 begin
1154   case WCh of
1155     Ord('0')..Ord('9'):       result := WCh - Ord('0');
1156     Ord('A')..Ord('F'):       result := WCh - Ord('A')+10;
1157     Ord('a')..Ord('f'):       result := WCh - Ord('a')+10;
1158     else                      result := -1;
1159   end;
1160 end;
1161
1162 {\90à\96¾ \81F  \82W\90i\90\94\82ð\95\\82·\95\8e\9a\82ð\8eó\82¯\8eæ\82è\81A\90®\90\94\82É\82µ\82Ä\95Ô\82·\81B
1163  \88ø\90\94 \81F  WCh: WChar_t;     8\90i\90\94\82ð\95\\82·1\83o\83C\83g\95\8e\9a [0-7]
1164
1165  \95Ô\82è\92l\81\90³\8fí\8e\9e\81F  0 <= result <= 7
1166           \88Ù\8fí\8e\9e\81F  -1}
1167 function OctWCharToInt(WCh: WChar_t): Integer;
1168 begin
1169   case WCh of
1170     Ord('0')..Ord('7'):       result := WCh - Ord('0');
1171     else                      result := -1;
1172   end;
1173 end;
1174
1175 {\8b@\94\\81F Str \82©\82ç \82P\95\8e\9a \93¾\82é
1176  \89ð\90à\81F Str\92\86\82ÅIndex\82ª\8ew\82·\88Ê\92u\82©\82ç1\95\8e\9a(\82Q\83o\83C\83g\95\8e\9a\8aÜ\82Þ) \93¾\82Ä\82©\82ç\81AIndex\82ª
1177         \8e\9f\82Ì\95\8e\9a\82ð\8ew\82·\82æ\82¤\82É\90i\82ß\82é
1178  \92\8d\88Ó\81F Index\82ª\95\8e\9a\97ñ\82Ì\92·\82³\82æ\82è\82·\82Å\82É\92·\82¢\8fê\8d\87\82Í\8fí\82É 0\82ð\95Ô\82µ\81AIndex\82ð\91\9d\82â\82³\82È\82¢\81B
1179         \82Â\82Ü\82è\81AIndex\82Í\8dÅ\91å\82Å\82à Length(Str)+1 \82Å\82 \82é\81B}
1180 function GetWChar(const Str: String; var Index: Integer): WChar_t;
1181 begin
1182   if (Index >= 1) and (Index <= Length(Str)) then begin
1183     if IsDBCSLeadByte(Byte(Str[Index])) then begin
1184       {Str\82Ì\8dÅ\8cã\82Ì\95\8e\9a\82ª\82Q\83o\83C\83g\95\8e\9a\83R\81[\83h\82Ì\82P\83o\83C\83g\82Ì\82Æ\82«\82Í\97á\8aO\90\90¬}
1185       if Index = Length(Str) then
1186         raise ERegExpParser.Create('\95s\90³\82È\82Q\83o\83C\83g\95\8e\9a\83R\81[\83h\82Å\82·\81B', Index);
1187       WordRec(result).Hi := Byte(Str[Index]);
1188       WordRec(result).Lo := Byte(Str[Index+1]);
1189       Inc(Index, 2);
1190     end else begin
1191       result := Byte(Str[Index]);
1192       Inc(Index);
1193     end;
1194   end else begin
1195     result := CONST_NULL;
1196   end;
1197 end;
1198
1199 //1997/09/25 FIX: MBUtils.pas\82ª\82È\82­\82Ä\82à\93®\8dì\82·\82é\82æ\82¤\82É\95Ï\8dX
1200 function IsTrailByteInStr(pText: PAnsiChar;
1201                           ptr:   PAnsiChar
1202                          ): Boolean;
1203 var
1204   p: PAnsiChar;
1205 begin
1206   Result := false;
1207   if pText = ptr then Exit;
1208   p := ptr - 1;
1209   while (p <> pText) do
1210   begin
1211     if not IsDBCSLeadByte(Ord(p^)) then Break;
1212     Dec(p);
1213   end;
1214   if ((ptr - p) mod 2) = 0 then Result := true;
1215 end;
1216
1217 procedure UnGetWChar(const Str: String; var Index: Integer);
1218 begin
1219   if Index <= 1 then
1220     Exit
1221   else if (Index > 2) and IsTrailByteInStr(PAnsiChar(Str), PAnsiChar(Str)+Index-2) then
1222     Dec(Index, 2)
1223   else
1224     Dec(Index);
1225 end;
1226
1227 function PCharGetWChar(var pText: PChar): WChar_t;
1228 begin
1229   if Byte(pText^) <> CONST_NULL then begin
1230     if IsDBCSLeadByte(Byte(pText^)) then begin
1231       WordRec(result).Hi := Byte(pText^);
1232       WordRec(result).Lo := Byte((pText+1)^);
1233       Inc(pText, 2);
1234     end else begin
1235       result := Byte(pText^);
1236       Inc(pText);
1237     end;
1238   end else begin
1239     result := CONST_NULL;
1240   end;
1241 end;
1242
1243 {\8b@\94\\81F WChar_t\8c^\82Ì\92l\82ðString\8c^\82Ö\95Ï\8a·\82·\82é\81B}
1244 function WCharToStr(WCh: WChar_t): String;
1245 begin
1246   if IsDBCSLeadByte(Hi(WCh)) then
1247     result := Chr(Hi(WCh))+Chr(Lo(WCh))
1248   else
1249     result := Chr(Lo(WCh));
1250 end;
1251
1252 {\8b@\94\\81F '\' \82Å \88ø\97p\82³\82ê\82½\83L\83\83\83\89\83N\83^\82ð\93¾\82é\81B \n, \t \\ ...
1253  \92\8d\88Ó\81F Index\82Í'\'\82Ì\8e\9f\82Ì\95\8e\9a\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82·\82é\81B}
1254 function GetQuotedWChar(const Str: String; var Index: Integer): WChar_t;
1255 var
1256   WCh: WChar_t;
1257 begin
1258   WCh := GetWChar(Str, Index);
1259   if WCh = 0 then
1260     raise ERegExpParser.Create('"\"\82Ì\8e\9f\82É\82Í\95\8e\9a\82ª\95K\97v\82Å\82·\81B', Index);
1261
1262   if WCh = CONST_b  then      {'b'}
1263     result := CONST_BS  {back space}
1264   else if WCh = CONST_r then {'r'}
1265     result := CONST_CR  {Carriage Return}
1266   else if WCh = CONST_n then {'n'}
1267     result := CONST_LF  {Line Feed}
1268   else if WCh = CONST_t then {'t'}
1269     result := CONST_TAB {tab}
1270   else if WCh = CONST_x then {'x'}
1271     result := HexStrToInt(Str, Index)
1272   else if OctWCharToInt(WCh) >= 0 then begin
1273     UnGetWChar(Str, Index); {WCh\82ð\96ß\82·}
1274     result := OctStrToInt(Str, Index);
1275   end else
1276     result := WCh;
1277 end;
1278
1279 {\90à\96¾ \81F  16\90i\90\94\95\\8bL\82Ì\95\8e\9a\97ñ\82ðWord\8c^\82Ì\90\94\92l\82É\95Ï\8a·\82·\82é\81B
1280 \88ø\90\94  \81F  Str: String     \95Ï\8a·\8c³\82Ì\95\8e\9a\97ñ
1281           Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
1282 \95Ô\82è\92l\81F  \95\8e\9a\97ñ\82ª\95\\82·Word\8c^\82Ì\92l}
1283 function HexStrToInt(const Str: String; var Index: Integer): Word;
1284 var
1285  Val, i: Integer;
1286  WCh: WChar_t;
1287 begin
1288   result := 0;
1289   i := 1;
1290   WCh := GetWChar(Str, Index);
1291   Val := HexWCharToInt(WCh);
1292   while (WCh <> CONST_NULL) and (Val >= 0) and (i < 5) do begin
1293     result := result * 16 + Val;
1294     WCh := GetWChar(Str, Index);
1295     Val := HexWCharToInt(WCh);
1296     Inc(i);
1297   end;
1298   if i = 1 then
1299     raise ERegExpParser.Create('\95s\90³\82È\82P\82U\90i\90\94\83R\81[\83h\95\\8bL\82Å\82·\81B', Index);
1300   if WCh <> CONST_NULL then
1301     UnGetWChar(Str, Index);
1302 end;
1303
1304 {\90à\96¾ \81F  \82W\90i\90\94\95\\8bL\82Ì\95\8e\9a\97ñ\82ðWord\8c^\82Ì\90\94\92l\82É\95Ï\8a·\82·\82é\81B
1305 \88ø\90\94  \81F  Str: String     \95Ï\8a·\8c³\82Ì\95\8e\9a\97ñ
1306           Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
1307 \95Ô\82è\92l\81F  \95\8e\9a\97ñ\82ª\95\\82·Word\8c^\82Ì\92l}
1308 function OctStrToInt(const Str: String; var Index: Integer): Word;
1309 var
1310   Val, i: Integer;
1311   WCh: WChar_t;
1312 begin
1313   result := 0;
1314   i := 1;
1315   WCh := GetWChar(Str, Index);
1316   Val := OctWCharToInt(WCh);
1317   while (WCh <> CONST_NULL) and (Val >= 0) and (i < 7) do begin
1318     if (result * 8 + Val) > $FFFF then
1319       raise ERegExpParser.Create('\95s\90³\82È\82W\90i\90\94\83R\81[\83h\95\\8bL\82Å\82·\81B', Index);
1320     result := result * 8 + Val;
1321     WCh := GetWChar(Str, Index);
1322     Val := OctWCharToInt(WCh);
1323     Inc(i);
1324   end;
1325   if i = 1 then
1326     raise ERegExpParser.Create('\95s\90³\82È\82W\90i\90\94\83R\81[\83h\95\\8bL\82Å\82·\81B', Index);
1327   if WCh <> CONST_NULL then
1328     UnGetWChar(Str, Index);
1329 end;
1330
1331 {\90à\96¾ \81F  FS:WChar_t\82ð\8bæ\90Ø\82è\95\8e\9a\82Æ\82µ\82Ä\81A\83o\83C\83g\88Ê\92uIndex\82©\82ç\8en\82Ü\82é\83g\81[\83N\83\93\82ð\82P\82Â\95Ô\82·\81B
1332 \88ø\90\94  \81F  Str: String
1333           Index: Integer  \88ø\90\94Str\82ÌIndex\94Ô\96Ú\82Ì\83o\83C\83g\88Ê\92u\82©\82ç\95Ï\8a·\82ð\8en\82ß\82é\81B
1334 \95Ô\82è\92l\81F  FS\82Å\8bæ\90Ø\82ç\82ê\82½\81A\83o\83C\83g\88Ê\92uIndex\82©\82ç\8en\82Ü\82é\83g\81[\83N\83\93}
1335 function WCharGetToken(const Str: String; var Index: Integer; FS: WChar_t): String;
1336 var
1337   WCh: WChar_t;
1338 begin
1339   result := '';
1340   WCh := GetWChar(Str, Index);
1341   while WCh <> 0 do begin
1342     if WCh = FS then
1343       break
1344     else begin
1345       result := result + WCharToStr(WCh);
1346       WCh := GetWChar(Str, Index);
1347     end;
1348   end;
1349 end;
1350
1351 {\90à\96¾ \81F  \88ø\90\94Str\92\86\82Ì\83\81\83^\83L\83\83\83\89\83N\83^\82É'\'\82ð\82Â\82¯\82é\81B
1352 \88ø\90\94  \81F  Str: String
1353 \95Ô\82è\92l\81F  \83\81\83^\83L\83\83\83\89\83N\83^\82Ì\91O\82É'\'\82ª\82Â\82¢\82½Str}
1354 function QuoteMetaWChar(Str: String): String;
1355 var
1356   i, j: Integer;
1357   WChar: WChar_t;
1358 begin
1359   result := '';
1360   i := 1;
1361   WChar := GetWChar(Str, i);
1362   while WChar <> 0 do begin
1363     j := 0;
1364     while j <= High(METACHARS) do begin
1365       if METACHARS[j] = WChar then
1366         break
1367       else
1368         Inc(j);
1369     end;
1370     if j <= High(METACHARS) then
1371       result := result + '\' + WCharToStr(WChar)
1372     else
1373       result := result + WCharToStr(WChar);
1374     WChar := GetWChar(Str, i);
1375   end;
1376
1377 end;
1378
1379 { -============================ TREScanner Class =================================-}
1380 constructor TREScanner.Create(Str: String);
1381 begin
1382   inherited Create;
1383   Self.SetRegExpStr(Str);
1384 end;
1385
1386 procedure TREScanner.SetRegExpStr(RegExpStr: String);
1387 begin
1388   FRegExpStr := RegExpStr;
1389   FIndex := 1;
1390 end;
1391
1392 {\8b@\94\\81\83g\81[\83N\83\93\82ð\93¾\82é
1393  \89ð\90à\81F GetWChar\82¨\82æ\82ÑUnGetWChar\83\81\83\\83b\83h\82ð\8eg\82Á\82Ä\83g\81[\83N\83\93\82ð\93¾\82é\81B
1394  \92\8d\88Ó\81\95Ô\82è\92l\82Í\81A\97ñ\8b\93\8c^ REToken_t\82Ì\82¤\82¿retk_CharClass\88È\8aO\82Ì\82Ç\82ê\82©}
1395 function TREScanner.GetTokenStd: REToken_t;
1396 var
1397   WChar: WChar_t;
1398 begin
1399   WChar := GetWChar(FRegExpStr, FIndex);
1400   FSymbol.WChar := WChar;
1401
1402   { \95\8e\9a(\97ñ)\82ð\83g\81[\83N\83\93\82É\95Ï\8a·\82·\82é }
1403   if WChar = CONST_NULL then
1404     FToken := retk_End
1405   else if WChar = CONST_DOLLAR then
1406     FToken := retk_LTail
1407   else if WChar = CONST_LPAR then
1408     FToken := retk_LPar
1409   else if WChar = CONST_RPAR then
1410     FToken := retk_RPar
1411   else if WChar = CONST_STAR then
1412     FToken := retk_Star
1413   else if WChar = CONST_PLUS then
1414     FToken := retk_Plus
1415   else if WChar = CONST_DOT then
1416     FToken := retk_Dot
1417   else if WChar = CONST_QMARK then
1418     FToken := retk_QMark
1419   else if WChar = CONST_VL then
1420     FToken := retk_Union
1421   else if WChar = CONST_RBRA then
1422     FToken := retk_RBra
1423   else if WChar = CONST_LBRA then begin
1424     WChar := GetWChar(FRegExpStr, FIndex);
1425     if WChar = CONST_NULL then
1426       raise ERegExpParser.Create('\89E\83u\83\89\83P\83b\83g"]"\82ª\95K\97v\82Å\82·', FIndex);
1427     if WChar = CONST_CARET then
1428       FToken := retk_LBraNeg {\95â\83L\83\83\83\89\83N\83^\83N\83\89\83X}
1429     else begin
1430       UnGetWChar(FRegExpStr, FIndex);
1431       FToken := retk_LBra;
1432     end;
1433   end
1434   else if WChar = CONST_YEN then begin
1435     FToken := retk_Char;
1436     FSymbol.WChar := GetQuotedWChar(FRegExpStr, FIndex);
1437   end
1438   else if WChar = CONST_CARET then begin
1439     FToken := retk_LHead;
1440   end else
1441     FToken := retk_Char;
1442
1443   result := FToken;
1444 end;
1445
1446 {\8b@\94\\81F '[]'\82Å\88Í\82Ü\82ê\82½\83L\83\83\83\89\83N\83^\83N\83\89\83X\90³\8bK\95\\8c»\82Ì\92\86\82Ì\83g\81[\83N\83\93\82ð\93¾\82é\81B
1447  \89ð\90à\81F GetWChar\82¨\82æ\82ÑUnGetWChar\83\81\83\\83b\83h\82ð\8eg\82Á\82Ä\83g\81[\83N\83\93\82ð\93¾\82é\81B
1448  \92\8d\88Ó\81\95Ô\82è\92l\82Í\81A\97ñ\8b\93\8c^ REToken_t\82Ì\82¤\82¿
1449         retk_Char, retk_CharClass, retk_RBra\82Ì\82Ç\82ê\82©\81B
1450         \83k\83\8b\81E\83L\83\83\83\89\83N\83^\82ð\8c©\82Â\82¯\82½\82Æ\82«\82Í\97á\8aO\82ð\90\90¬\82·\82é\81B}
1451 function TREScanner.GetTokenCC: REToken_t;
1452 var
1453   WChar, WChar2, WChar3: WChar_t;
1454 begin
1455   WChar := GetWChar(FRegExpStr, FIndex);
1456   FSymbol.WChar := WChar;
1457
1458   { \95\8e\9a(\97ñ)\82ð\83g\81[\83N\83\93\82É\95Ï\8a·\82·\82é }
1459   if WChar = CONST_NULL then
1460     raise ERegExpParser.Create('\89E\83u\83\89\83P\83b\83g"]"\82ª\95K\97v\82Å\82·', FIndex);
1461   if WChar = CONST_RBRA then
1462     FToken := retk_RBra
1463   else begin
1464     if WChar = CONST_YEN then
1465     {\83G\83X\83P\81[\83v\83V\81[\83P\83\93\83X\82ð\8f\88\97\9d}
1466       WChar := GetQuotedWChar(FRegExpStr, FIndex);
1467
1468     {\83L\83\83\83\89\83N\83^\94Í\88Í\82ð\95\\82·'-'\82É\8aÖ\82·\82é\8f\88\97\9d\82ð\82·\82é}
1469     FToken := retk_Char;
1470     WChar2 := GetWChar(FRegExpStr, FIndex);
1471     if WChar2 = CONST_MINUS then begin
1472     {2\94Ô\96Ú\82Ì\95\8e\9a\82ª'-'\82¾\82Á\82½\82Æ\82«}
1473       WChar3 := GetWChar(FRegExpStr, FIndex);
1474       if WChar3 = CONST_NULL then
1475       {3\94Ô\96Ú\82Ì\95\8e\9a\82ª\83k\83\8b\83L\83\83\83\89\83N\83^\82Ì\82Æ\82«}
1476         raise ERegExpParser.Create('\89E\83u\83\89\83P\83b\83g"]"\82ª\95K\97v\82Å\82·', FIndex);
1477
1478       if WChar3 = CONST_RBRA then begin
1479       {3\94Ô\96Ú\82Ì\95\8e\9a\82ª ']'\82Ì\82Æ\82«}
1480         UnGetWChar(FRegExpStr, FIndex); { WChar3\82ð\96ß\82· }
1481         UnGetWChar(FRegExpStr, FIndex); { WChar2\82ð\96ß\82· }
1482         FSymbol.WChar := WChar;
1483       end else begin
1484         if WChar3 = CONST_YEN then
1485           WChar3 := GetQuotedWChar(FRegExpStr, FIndex);
1486         FToken := retk_CharClass;
1487         if WChar > WChar3 then
1488           raise ERegExpParser.Create('\95s\90³\82È\83L\83\83\83\89\83N\83^\94Í\88Í\82Å\82·', FIndex);
1489         FSymbol.CharClass.StartChar := WChar;
1490         FSymbol.CharClass.EndChar := WChar3;
1491       end
1492     end else begin
1493     {2\94Ô\96Ú\82Ì\95\8e\9a\82ª'-'\82Å\82Í\82È\82¢\82Æ\82«}
1494       if WChar2 = CONST_NULL then
1495       {2\94Ô\96Ú\82Ì\95\8e\9a\82ª\83k\83\8b\83L\83\83\83\89\83N\83^\82Ì\82Æ\82«}
1496         raise ERegExpParser.Create('\89E\83u\83\89\83P\83b\83g"]"\82ª\95K\97v\82Å\82·', FIndex);
1497       UnGetWChar(FRegExpStr, FIndex);{WChar2\82ð\96ß\82·}
1498       FSymbol.WChar := WChar;
1499     end;
1500   end;
1501   result := FToken;
1502 end;
1503
1504 function TREScanner.GetToken: REToken_t;
1505 begin
1506   if FInCharClass then begin
1507     result := GetTokenCC;
1508     if result = retk_RBra then
1509       FInCharClass := False;
1510   end else begin
1511     result := GetTokenStd;
1512     if (result = retk_LBra) or (result = retk_LBraNeg) then
1513       FInCharClass := True;
1514   end;
1515 end;
1516
1517 constructor TREPreProcessor.Create(Str: String);
1518 begin
1519   inherited Create;
1520   FScanner := TREScanner.Create(Str);
1521   FTokenList := TList.Create;
1522   FListOfSynonymDic := TList.Create;
1523   FListOfFuzzyCharDic := TList.Create;
1524 end;
1525
1526 destructor TREPreProcessor.Destroy;
1527 begin
1528   FScanner.Free;
1529   DestroyTokenListItems;
1530   FTokenList.Free;
1531   FListOfSynonymDic.Free;
1532   FListOfFuzzyCharDic.Free;
1533   inherited Destroy;
1534 end;
1535
1536 {\90à\96¾ \81F    FTokenList: TList \82ð\81A\83A\83C\83e\83\80\83f\81[\83^ (RETokenInfo_t\8c^\83\8c\83R\81[\83h)\82Æ\8b¤\82É\94p\8aü\82·\82é\81B
1537 \92\8d\88Ó  \81F    MakeTokenList\82Æ\91Î\82Å\8eg\97p\82·\82é\81B}
1538 procedure TREPreProcessor.DestroyTokenListItems;
1539 var
1540   i: Integer;
1541 begin
1542   if FTokenList = nil then
1543     exit;
1544
1545   i := 0;
1546   while i < FTokenList.Count do begin
1547     Dispose(REpTokenInfo_t(FTokenList.Items[i]));
1548     FTokenList.Items[i] := nil;
1549     Inc(i);
1550   end;
1551   FTokenList.Clear;
1552 end;
1553
1554 {\90à\96¾ \81F    FTokenList: TList\82É RETokenInfo_t\8c^\82Ì\83\8c\83R\81[\83h\82ð\8d\\92z\82·\82é\81B
1555 \93®\8dì  \81F    \8dÅ\8cã\94ö\82ÌRETokenInfo_t\8c^\83\8c\83R\81[\83h\82Í\81A\8fí\82ÉToken = retk_End\82Å\82 \82é\81B
1556 \92\8d\88Ó  \81F    DestroyTokenList\83\81\83\\83b\83h\82Æ\91Î\82Å\8eg\97p\82·\82é\81B}
1557 procedure TREPreProcessor.MakeTokenList;
1558 var
1559   pTokenInfo: REpTokenInfo_t;
1560   prevIndex: Integer;
1561 begin
1562   prevIndex := FScanner.Index;
1563   DestroyTokenListItems;
1564   while FScanner.GetToken <> retk_End do begin
1565     New(pTokenInfo);
1566     try
1567       FTokenList.Add(pTokenInfo);
1568     except
1569       on Exception do begin
1570         Dispose(pTokenInfo);
1571         raise;
1572       end;
1573     end;
1574     with pTokenInfo^ do begin
1575       Token := FScanner.Token;
1576       Symbol := FScanner.Symbol;
1577       FromIndex := prevIndex;
1578       ToIndex := FScanner.Index;
1579     end;
1580     prevIndex := FScanner.Index;
1581   end;
1582
1583   {\8dÅ\8cã\94ö retk_End}
1584   New(pTokenInfo);
1585   try
1586     FTokenList.Add(pTokenInfo);
1587   except
1588     on Exception do begin
1589       Dispose(pTokenInfo);
1590       raise;
1591     end;
1592   end;
1593   with pTokenInfo^ do begin
1594     Token := retk_End;
1595     Symbol.WChar := CONST_NULL;
1596     FromIndex := 0;
1597     ToIndex := 0;
1598   end;
1599 end;
1600
1601 function TREPreProcessor.GetTargetRegExpStr: String;
1602 begin
1603   result := FScanner.RegExpStr;
1604 end;
1605
1606 procedure TREPreProcessor.SetTargetRegExpStr(Str: String);
1607 begin
1608   FScanner.RegExpStr := Str;
1609 end;
1610
1611 {\90à\96¾ \81F    \90³\8bK\95\\8c»\95\8e\9a\97ñ\82É\93¯\88Ó\8cê\82ð\91g\82Ý\8d\9e\82Þ\81B}
1612 procedure TREPreProcessor.Run;
1613 begin
1614   FProcessedRegExpStr := FScanner.RegExpStr;
1615   if FUseSynonymDic then begin
1616     Self.Process(FindSynonym);
1617     FScanner.RegExpStr := FProcessedRegExpStr;
1618   end;
1619
1620   if FUseFuzzyCharDic then
1621     Self.Process(FindFuzzyWChar);
1622 end;
1623
1624 {\90à\96¾ \81F    \93¯\88Ó\8cê\96\84\82ß\8d\9e\82Ý\8f\88\97\9d Run\83\81\83\\83b\83h\82Ì\89º\90¿\82¯}
1625 procedure TREPreProcessor.Process(FindFunc: TREPreProcessorFindFunc);
1626 var
1627   j, k: Integer;
1628   TkIndex: Integer;
1629   Info: RETokenInfo_t;
1630   InCC: Boolean;
1631 begin
1632   FProcessedRegExpStr := '';
1633   MakeTokenList;
1634   InCC := False;
1635   TkIndex := 0;
1636   {\82·\82×\82Ä\82Ì\83g\81[\83N\83\93\82ð\8c\9f\8d¸\82·\82é}
1637   while TkIndex < FTokenList.Count do begin
1638     Info := REpTokenInfo_t(FTokenList[TkIndex])^;
1639     {\83L\83\83\83\89\83N\83^\83N\83\89\83X ('[]'\82Å\82­\82­\82ç\82ê\82½\95\94\95ª)\82É\93ü\82é}
1640     if Info.Token = retk_LBra then
1641       InCC := True;
1642
1643     {\83L\83\83\83\89\83N\83^\83N\83\89\83X\82©\82ç\8fo\82½}
1644     if Info.Token = retk_RBra then
1645       InCC := False;
1646
1647     {\83g\81[\83N\83\93\82ª\83L\83\83\83\89\83N\83^\88È\8aO\82©\81A\83L\83\83\83\89\83N\83^\83N\83\89\83X '[ ]'\82Ì\92\86\82Ì\8fê\8d\87}
1648     if (Info.Token <> retk_Char) or InCC then begin
1649       FProcessedRegExpStr := FProcessedRegExpStr +
1650         Copy(FScanner.RegExpStr, Info.FromIndex, Info.ToIndex-Info.FromIndex);
1651       Inc(TkIndex); {\89½\82à\82¹\82¸\82ÉFProcessedRegExpStr\82Ö\92Ç\89Á}
1652     {\83g\81[\83N\83\93\82ª\83L\83\83\83\89\83N\83^\82Ì\8fê\8d\87}
1653     end else begin
1654       j := TkIndex;
1655       {j\82ª\83L\83\83\83\89\83N\83^\88È\8aO\82ð\8ew\82·\82Ü\82Å\83C\83\93\83N\83\8a\83\81\83\93\83g}
1656       while REpTokenInfo_t(FTokenList[j])^.Token = retk_Char do
1657         Inc(j);
1658
1659       {\83L\83\83\83\89\83N\83^\82Ì\98A\91±\82ð\82P\82Â\82Ã\82Â\8c\9f\8d¸}
1660       while TkIndex < j do begin
1661         k := FindFunc(TkIndex, j);
1662         if k <> -1 then begin
1663           {\83}\83b\83`\82µ\82½\95\94\95ª\82ð\92Ç\89Á}
1664           FProcessedRegExpStr := FProcessedRegExpStr + FSynonymStr;
1665           TkIndex := k; {\8e\9f\82Ì\83g\81[\83N\83\93\82©\82ç\83}\83b\83`\82·\82é\95\94\95ª\82ð\88ø\82«\91±\82«\82³\82ª\82·\81B}
1666         end else begin
1667           {\83}\83b\83`\82µ\82È\82¯\82ê\82Î\81A\88ê\95\8e\9a\95ª\92Ç\89Á\82µ\82Ä\81A\83C\83\93\83f\83b\83N\83X\82ð\90i\82ß\82é}
1668           Info := REpTokenInfo_t(FTokenList[TkIndex])^;
1669           FProcessedRegExpStr := FProcessedRegExpStr +
1670             Copy(FScanner.RegExpStr, Info.FromIndex, Info.ToIndex-Info.FromIndex);;
1671           Inc(TkIndex);
1672         end;
1673       end;
1674       TkIndex := j;
1675     end;
1676   end;
1677 end;
1678
1679 {\90à\96¾ \81F    \93¯\88Ó\8cê\8e«\8f\91 SynonymDic: TList\82ð\8eg\82Á\82Ä\81A\93¯\88Ó\8cê\82ð\92T\82·\81B
1680 \95Ô\82è\92l\81F    \83g\81[\83N\83\93\83\8a\83X\83g\93à\82Ì\93¯\88Ó\8cê\82Ì\8e\9f\82Ì\83C\83\93\83f\83b\83N\83X
1681             \8c©\82Â\82©\82ç\82È\82¯\82ê\82Π-1}
1682 function TREPreProcessor.ReferToOneList(FromTokenIndex, ToTokenIndex: Integer; SynonymDic: TList): Integer;
1683 var
1684   StrList: TStrings;
1685   i, j, k, m: Integer;
1686
1687   {Str\82ÆFTokenList\82ð\94ä\8ar}
1688   function Match(Str: String): Integer;
1689   var
1690     StrIndex, TkIndex: Integer;
1691     WChar: WChar_t;
1692   begin
1693     if Str = '' then begin
1694       result := -1;
1695       exit;
1696     end;
1697
1698     TkIndex := FromTokenIndex;
1699     StrIndex := 1;
1700     WChar := GetWChar(Str, StrIndex);
1701     while (WChar <> CONST_NULL) and (TkIndex < ToTokenIndex) do begin
1702       if WChar <> REpTokenInfo_t(FTokenList[TkIndex])^.Symbol.WChar then begin
1703         result := -1;
1704         exit;
1705       end else begin
1706         Inc(TkIndex);
1707         WChar := GetWChar(Str, StrIndex);
1708       end;
1709     end;
1710     if WChar = CONST_NULL then
1711       result := TkIndex
1712     else
1713       result := -1;
1714   end;
1715 begin
1716   result := -1;
1717   i := 0;
1718   while i < SynonymDic.Count do begin
1719     StrList := TStrings(SynonymDic[i]);
1720     j := 0;
1721     while j < StrList.Count do begin
1722       k := Match(StrList[j]);
1723       if k <> -1 then begin
1724       {\83}\83b\83`\82µ\82½}
1725         FSynonymStr := '(' + QuoteMetaWChar(StrList[0]);
1726         m := 1;
1727         while m < StrList.Count do begin
1728           FSynonymStr := FSynonymStr + '|' + QuoteMetaWChar(StrList[m]);
1729           Inc(m);
1730         end;
1731         FSynonymStr := FSynonymStr + ')';
1732         result := k;
1733         exit;
1734       end;
1735       Inc(j);
1736     end;
1737     Inc(i);
1738   end;
1739 end;
1740
1741 {\90à\96¾ \81F
1742 \95Ô\82è\92l\81F    \83g\81[\83N\83\93\83\8a\83X\83g\93à\82Ì\93¯\88Ó\8cê\82Ì\8e\9f\82Ì\83C\83\93\83f\83b\83N\83X
1743             \8c©\82Â\82©\82ç\82È\82¯\82ê\82Π-1
1744 \92\8d\88Ó  \81F    Run\83\81\83\\83b\83h\82ª\83\81\83\\83b\83h\83|\83C\83\93\83^\82ðProcess\83\81\83\\83b\83h\82É\93n\82µ\81A
1745             Process\83\81\83\\83b\83h\82ª\8cÄ\82Ñ\8fo\82·\81B}
1746 function TREPreProcessor.FindSynonym(FromTokenIndex, ToTokenIndex: Integer): Integer;
1747 var
1748   i: Integer;
1749 begin
1750   result := -1;
1751   i := 0;
1752   while i < FListOfSynonymDic.Count do begin
1753     result := ReferToOneList(FromTokenIndex, ToTokenIndex, FListOfSynonymDic[i]);
1754     if result <> -1 then
1755       exit;
1756     Inc(i);
1757   end;
1758 end;
1759
1760 {\90à\96¾ \81F
1761 \95Ô\82è\92l\81F    \83g\81[\83N\83\93\83\8a\83X\83g\93à\82Ì\93¯\88Ó\8cê\82Ì\8e\9f\82Ì\83C\83\93\83f\83b\83N\83X
1762             \8c©\82Â\82©\82ç\82È\82¯\82ê\82Π-1
1763 \92\8d\88Ó  \81F    Run\83\81\83\\83b\83h\82ª\83\81\83\\83b\83h\83|\83C\83\93\83^\82ðProcess\83\81\83\\83b\83h\82É\93n\82µ\81A
1764             Process\83\81\83\\83b\83h\82ª\8cÄ\82Ñ\8fo\82·\81B}
1765 function TREPreProcessor.FindFuzzyWChar(FromTokenIndex, ToTokenIndex: Integer): Integer;
1766 var
1767   i: Integer;
1768 begin
1769   result := -1;
1770   i := 0;
1771   while i < FListOfFuzzyCharDic.Count do begin
1772     result := ReferToOneList(FromTokenIndex, ToTokenIndex, FListOfFuzzyCharDic[i]);
1773     if result <> -1 then
1774       exit;
1775     Inc(i);
1776   end;
1777 end;
1778
1779 constructor TREParseTree.Create;
1780 begin
1781   inherited Create;
1782   FNodeList := TList.Create;
1783   FLeafList := TList.Create;
1784 end;
1785
1786 destructor TREParseTree.Destroy;
1787 begin
1788   DisposeTree;
1789   FNodeList.Free;
1790   FLeafList.Free;
1791   inherited Destroy;
1792 end;
1793
1794 {\8d\\95\96Ø\82Ì\83m\81[\83h\82ð\8dì\90¬\82·\82é\81B
1795   op \82Í\83m\81[\83h\82ª\95\\82·\89\89\8eZ\81Aleft\82Í\8d\82Ì\8eq\81Aright\82Í\89E\82Ì\8eq }
1796 function TREParseTree.MakeInternalNode(TheOp: REOperation_t; pLeft,
1797   pRight: REpNode_t): REpNode_t;
1798 begin
1799   New(result);
1800   with result^ do begin
1801     op := TheOp;
1802     Children.pLeft := pLeft;
1803     Children.pRight := pRight;
1804   end;
1805   try
1806     FNodeList.Add(result);
1807   except
1808     {TList\82Å\83\81\83\82\83\8a\95s\91«\82Ì\8e\9e\82Í,\90V\82µ\82¢\8d\\95\96Ø\82Ì\90ß\82à\8aJ\95ú\82µ\82Ä\82µ\82Ü\82¤}
1809     on EOutOfMemory do begin
1810       Dispose(result);
1811       raise;
1812     end;
1813   end;
1814 end;
1815
1816 {\8d\\95\96Ø\82Ì\97t\82ð\8dì\82é
1817   TheC \82Í\82±\82Ì\97t\82ª\95\\82·\95\8e\9a}
1818 function TREParseTree.MakeLeaf(aStartChar, aEndChar: WChar_t): REpNode_t;  {char}
1819 var
1820   i: Integer;
1821 begin
1822   {\8aù\82É\93¯\82\83L\83\83\83\89\83N\83^\83N\83\89\83X\82ð\8e\9d\82Â\97t\82ª\91\8dÝ\82·\82ê\82Î\81A\82»\82ê\82ð\95Ô\82·\81B}
1823   for i := 0 to FLeafList.Count-1 do begin
1824     if (REpNode_t(FLeafList[i])^.CharClass.StartChar = aStartChar) and
1825     (REpNode_t(FLeafList[i])^.CharClass.EndChar = aEndChar) then begin
1826       result := FLeafList[i];
1827       exit;
1828     end;
1829   end;
1830
1831   New(result);
1832   with result^ do begin
1833     op := reop_char;
1834     CharClass.StartChar := aStartChar;
1835     CharClass.EndChar := aEndChar;
1836   end;
1837   try
1838     FLeafList.Add(result);
1839   except
1840     {TList\82Å\83\81\83\82\83\8a\95s\91«\82Ì\8e\9e\82Í,\90V\82µ\82¢\8d\\95\96Ø\82Ì\90ß\82à\8aJ\95ú\82µ\82Ä\82µ\82Ü\82¤}
1841     on EOutOfMemory do begin
1842       Dispose(result);
1843       raise;
1844     end;
1845   end;
1846 end;
1847
1848 {\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\90ß\81\81¦\8eq\82ð\8e\9d\82½\82È\82¢\82ª\81AMakeInternalNode\82ð\8eg\82¤}
1849 function TREParseTree.MakeLHeadNode(WChar: WChar_t): REpNode_t;
1850 begin
1851   result := MakeInternalNode(reop_LHead, nil, nil);
1852   with result^ do begin
1853     CharClass.StartChar := WChar;
1854     CharClass.EndChar := WChar;
1855   end;
1856 end;
1857
1858 {\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82ð\95\\82·\90ß\81\81¦\8eq\82ð\8e\9d\82½\82È\82¢\82ª\81AMakeInternalNode\82ð\8eg\82¤}
1859 function TREParseTree.MakeLTailNode(WChar: WChar_t): REpNode_t;
1860 begin
1861   result := MakeInternalNode(reop_LTail, nil, nil);
1862   with result^ do begin
1863     CharClass.StartChar := WChar;
1864     CharClass.EndChar := WChar;
1865   end;
1866 end;
1867
1868 {\94C\88Ó\82Ì\88ê\95\8e\9a\82ð\95\\82·'.'\83\81\83^\83L\83\83\83\89\83N\83^\82É\91Î\89\9e\82·\82é\95\94\95ª\96Ø\82ð\8dì\82é\81B
1869  \81¦CR LF\82ð\8f\9c\82­\91S\82Ä\82Ì\83L\83\83\83\89\83N\83^\82ð\95\\82·\97t\82ðreop_Union\91\80\8dì\82ð\95\\82·\92\86\8aÔ\90ß\82Å\8c\8b\82ñ\82¾\82à\82Ì}
1870 function TREParseTree.MakeAnyCharsNode: REpNode_t;
1871 begin
1872     result := MakeInternalNode(reop_Union, MakeLeaf($1, $09), MakeLeaf($0B, $0C));
1873     result := MakeInternalNode(reop_Union, result, MakeLeaf($0E, $FCFC));
1874 end;
1875
1876 {\88ø\90\94\82ª aStartChar <= aEndChar \82Ì\8aÖ\8cW\82ð\96\9e\82½\82µ\82Ä\82¢\82é\82Æ\82«\82É\81AMakeLeaf\82ð\8cÄ\82Ô
1877  \82»\82ê\88È\8aO\82Í\81Anil \82ð\95Ô\82·\81B}
1878 function TREParseTree.Check_and_MakeLeaf(aStartChar, aEndChar: WChar_t):REpNode_t;
1879 begin
1880   if aStartChar <= aEndChar then begin
1881     result := MakeLeaf(aStartChar, aEndChar);
1882   end else
1883     result := nil;
1884 end;
1885
1886 {\97t\82ð\93à\95\94\90ß\82É\95Ï\82¦\82é\81B}
1887 procedure TREParseTree.ChangeLeaftoNode(pLeaf, pLeft, pRight: REpNode_t);
1888 begin
1889   if (pLeft = nil) or (pRight = nil) then
1890     raise Exception.Create('TREParseTree : \92v\96½\93I\83G\83\89\81[');{ debug }
1891   with pLeaf^ do begin
1892     op := reop_Union;
1893     Children.pLeft := pLeft;
1894     Children.pRight := pRight;
1895   end;
1896   FLeafList.Remove(pLeaf);
1897   try
1898     FNodeList.Add(pLeaf);
1899   except
1900   on EOutOfMemory do begin
1901     FreeMem(pLeaf, SizeOf(RENode_t));
1902     raise;
1903     end;
1904   end;
1905 end;
1906
1907 {\8b@\94\\81\8cÂ\81X\82Ì\97t\82ª\8e\9d\82Â\83L\83\83\83\89\83N\83^\94Í\88Í\82ª\82P\82Â\82à\8fd\95¡\82µ\82È\82¢\82æ\82¤\82É\82·\82é\81B
1908  \89ð\90à\81\97t\82Í\81ACharClass\83t\83B\81[\83\8b\83h\82ð\8e\9d\82¿\81ACharClass\83t\83B\81[\83\8b\83h\82ÍStartChar\82ÆEndChar
1909         \82ð\83t\83B\81[\83\8b\83h\82É\8e\9d\82Â\83\8c\83R\81[\83h\82Å\82 \82é\81B
1910         \8cÂ\81X\82Ì\97t\82ª\8e\9d\82Â\83L\83\83\83\89\83N\83^\82Ì\94Í\88Í\82ª\8fd\95¡\82µ\82È\82¢\82©\92²\82×\82Ä\81A\8fd\95¡\82·\82é\8fê\8d\87\82É\82Í\81A
1911         \82»\82Ì\97t\82ð\95ª\8a\84\82µ\81Areop_Union\82ð\8e\9d\82Â\93à\95\94\90ß\82Å\93\99\89¿\82È\95\94\95ª\96Ø\82É\92¼\82·\81B}
1912 procedure TREParseTree.ForceCharClassUnique;
1913 var
1914   i, j: Integer;
1915   Changed: Boolean;
1916
1917   {\8b@\94\\81\8fd\95¡\82·\82é\83L\83\83\83\89\83N\83^\94Í\88Í\82ð\82à\82Â\97t\82Ì\95ª\8a\84
1918    \89ð\90à\81\82Q\82Â\82Ì\97tpCCLeaf1\82ÆpCCLeaf2\82Ì\83L\83\83\83\89\83N\83^\94Í\88Í\82ð\92²\82×\82Ä\81A\8fd\95¡\82·\82é\82Æ\82«\82Í
1919           \95ª\8a\84\82·\82é\82µ\82Ä\93\99\89¿\82È\95\94\95ª\96Ø\82É\95Ï\8a·\82·\82é\81B}
1920   function SplitCharClass(pCCLeaf1, pCCLeaf2: REpNode_t): Boolean;
1921   var
1922     pNode1, pNode2, pNode3: REpNode_t;
1923     S1, S2, SmallE, BigE: WChar_t;
1924   begin
1925     result := False;
1926     {\91O\8f\88\97\9d\81F pCCLeaf1 \82ÌStartChar <= pCCLeaf2 \82ÌStartChar \82ð\95Û\8fØ\82·\82é}
1927     if pCCLeaf1^.CharClass.StartChar > pCCLeaf2^.CharClass.StartChar then begin
1928       pNode1 := pCCLeaf1;
1929       pCCLeaf1 := pCCLeaf2;
1930       pCCLeaf2 := pNode1;
1931     end;
1932
1933     {\83L\83\83\83\89\83N\83^\83N\83\89\83X\82Ì\94Í\88Í\82ª\8fd\95¡\82µ\82È\82¢ \96\94\82Í \93¯\88ê\82È\82ç\82ΠExit
1934      \81¦ MakeLeaf\83\81\83\\83b\83h\82Ì\8d\\91¢\82©\82ç\82¢\82Á\82Ä\8dÅ\8f\89\82Í\8fd\95¡\82·\82é\8e\96\82Í\82È\82¢\82ª\81A\95ª\8a\84\82ð\8cJ\82è\95Ô\82·
1935         \82Æ\8fd\95¡\82·\82é\89Â\94\\90«\82ª\82 \82é\81B}
1936     if (pCCLeaf1^.CharClass.EndChar < pCCLeaf2^.CharClass.StartChar) or
1937     (pCCLeaf1^.CharClass.Chars = pCCLeaf2^.CharClass.Chars) then
1938       exit;
1939
1940     {(pCCLeaf1 \82ÌStartChar) S1 <= S2 (pCCLeaf2 \82ÌStartChar)}
1941     S1 := pCCLeaf1^.CharClass.StartChar;
1942     S2 := pCCLeaf2^.CharClass.StartChar;
1943
1944     {SmallE \82Í\81ApCCLeaf1, pCCLeaf2 \82Ì EndChar \82Ì\8f¬\82³\82¢\95û
1945      SmallE <= E2}
1946     if pCCLeaf1^.CharClass.EndChar > pCCLeaf2^.CharClass.EndChar then begin
1947       SmallE := pCCLeaf2^.CharClass.EndChar;
1948       BigE := pCCLeaf1^.CharClass.EndChar;
1949     end else begin
1950       SmallE := pCCLeaf1^.CharClass.EndChar;
1951       BigE := pCCLeaf2^.CharClass.EndChar;
1952     end;
1953
1954     pNode1 := Check_and_MakeLeaf(S1, S2-1);
1955     pNode2 := Check_and_MakeLeaf(S2, SmallE);
1956     pNode3 := Check_and_MakeLeaf(SmallE+1, BigE);
1957     {if (pNode1 = nil) and (pNode2 = nil) and (pNode3 = nil) then
1958       raise ERegExpParser.Create('\92v\96½\93I\82È\83G\83\89\81[', 0); }
1959     if pNode1 = nil then begin {S1 = S2 \82Ì\82Æ\82«}
1960       if pCCLeaf1^.CharClass.EndChar = BigE then
1961         ChangeLeaftoNode(pCCLeaf1, pNode2, pNode3)
1962       else
1963         ChangeLeaftoNode(pCCLeaf2, pNode2, pNode3);
1964     end else if pNode3 = nil then begin {SmallE = BigE \82Ì\8e\9e}
1965       ChangeLeaftoNode(pCCLeaf1, pNode1, pNode2);
1966     end else begin
1967       if pCCLeaf1^.CharClass.EndChar = BigE then begin{pCCLeaf1\82ÉpCCLeaf2\82ª\8aÜ\82Ü\82ê\82é}
1968         ChangeLeaftoNode(pCCLeaf1, MakeInternalNode(reop_Union, pNode1, pNode2),
1969           pNode3)
1970       end else begin {pCCLeaf1 \82Æ pCCLeaf2 \82Ì\82P\95\94\95ª\82ª\8fd\82È\82Á\82Ä\82¢\82é}
1971         ChangeLeaftoNode(pCCLeaf1, pNode1, pNode2);
1972         ChangeLeaftoNode(pCCLeaf2, pNode2, pNode3);
1973       end;
1974     end;
1975     result := True;
1976   end;
1977 begin {procedure TREParser.ForceCharClassUnique}
1978   i := 0;
1979   while i < LeafList.Count do begin
1980     j := i + 1;
1981     Changed := False;
1982     while j < LeafList.Count do begin
1983       Changed := SplitCharClass(LeafList[j], LeafList[i]);
1984       if not Changed then
1985         Inc(j)
1986       else
1987         break;
1988     end;
1989     if not Changed then
1990       Inc(i);
1991   end;
1992 end; {procedure TREParser.ForceCharClassUnique}
1993
1994 procedure TREParseTree.DisposeTree;
1995 var
1996   i: Integer;
1997 begin
1998   if FNodeList <> nil then begin
1999     for i := 0 to FNodeList.Count - 1 do begin
2000       if FNodeList[i] <> nil then
2001         Dispose(REpNode_t(FNodeList.Items[i]));
2002     end;
2003     FNodeList.Clear;
2004   end;
2005
2006   if FLeafList <> nil then begin
2007     for i := 0 to FLeafList.Count -1 do begin
2008       if FLeafList[i] <> nil then
2009         Dispose(REpNode_t(FLeafList[i]));
2010     end;
2011     FLeafList.Clear;
2012   end;
2013   FpHeadNode := nil;
2014 end;
2015
2016 {-=========================== TREParser Class ===============================-}
2017 constructor TREParser.Create(RegExpStr: String);
2018 begin
2019   inherited Create;
2020   FScanner := TREScanner.Create(RegExpStr);
2021   FParseTree := TREParseTree.Create;
2022   {\8f\80\94õ\8a®\97¹\81B Run\83\81\83\\83b\83h\82ð\8cÄ\82×\82Î\8d\\95\89ð\90Í\82ð\82·\82é\81B}
2023 end;
2024
2025 destructor TREParser.Destroy;
2026 begin
2027   FScanner.Free;
2028   FParseTree.Free;
2029   inherited Destroy;
2030 end;
2031
2032 {**************************************************************************
2033   \90³\8bK\95\\8c»\82ð\83p\81[\83X\82·\82é\83\81\83\\83b\83h\8cQ
2034  **************************************************************************}
2035 procedure TREParser.Run;
2036 begin
2037   FParseTree.DisposeTree; {\82·\82Å\82É\82 \82é\8d\\95\96Ø\82ð\94p\8aü\82µ\82Ä\8f\89\8aú\89»}
2038
2039   FScanner.GetToken; {\8dÅ\8f\89\82Ì\83g\81[\83N\83\93\82ð\93Ç\82Ý\8d\9e\82Þ}
2040
2041   {\90³\8bK\95\\8c»\82ð\83p\81[\83X\82·\82é}
2042   FParseTree.pHeadNode := regexp;
2043
2044   {\8e\9f\82Ì\83g\81[\83N\83\93\82ªretk_End \82Å\82È\82¯\82ê\82Î\83G\83\89\81[}
2045   if FScanner.Token <> retk_End then begin
2046     raise ERegExpParser.Create('\90³\8bK\95\\8c»\82É\97]\95ª\82È\95\8e\9a\82ª\82 \82è\82Ü\82·',
2047       FScanner.Index);
2048   end;
2049
2050   FParseTree.ForceCharClassUnique;{\83L\83\83\83\89\83N\83^\83N\83\89\83X\82ð\95ª\8a\84\82µ\82Ä\83\86\83j\81[\83N\82É\82·\82é}
2051 end;
2052
2053 { <regexp>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
2054   \91I\91ð X|Y \82ð\89ð\90Í\82·\82é }
2055 function TREParser.regexp: REpNode_t;
2056 begin
2057   result := term;
2058   while FScanner.Token = retk_Union do begin
2059     FScanner.GetToken;
2060     result := FParseTree.MakeInternalNode(reop_union, result, term);
2061   end;
2062 end;
2063
2064 { <term>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·
2065   \98A\8c\8b\82w\82x\82ð\89ð\90Í\82·\82é}
2066 function TREParser.Term: REpNode_t;
2067 begin
2068   if (FScanner.Token = retk_Union) or
2069      (FScanner.Token = retk_RPar) or
2070      (FScanner.Token = retk_End) then
2071     result := FParseTree.MakeInternalNode(reop_Empty, nil, nil)
2072   else begin
2073     result := factor;
2074     while (FScanner.Token <> retk_Union) and
2075           (FScanner.Token <> retk_RPar) and
2076           (FScanner.Token <> retk_End) do begin
2077       result := FParseTree.MakeInternalNode(reop_concat, result, factor);
2078     end;
2079   end;
2080 end;
2081
2082 { <factor>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·
2083   \8cJ\82è\95Ô\82µX*, X+, X?\82ð\89ð\90Í\82·\82é}
2084 function TREParser.Factor: REpNode_t;
2085 begin
2086   result := primary;
2087   if FScanner.Token = retk_Star then begin
2088     result := FParseTree.MakeInternalNode(reop_closure, result, nil);
2089     FScanner.GetToken;
2090   end else if FScanner.Token = retk_Plus then begin
2091     result := FParseTree.MakeInternalNode(reop_concat, result,
2092       FParseTree.MakeInternalNode(reop_closure, result, nil));
2093     FScanner.GetToken;
2094   end else if FScanner.Token = retk_QMark then begin
2095     result := FParseTree.MakeInternalNode(reop_Union, result,
2096       FParseTree.MakeInternalNode(reop_Empty, nil, nil));
2097     FScanner.GetToken;
2098   end;
2099 end;
2100
2101 { <primary>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
2102   \95\8e\9a\82»\82Ì\82à\82Ì\81A(X)\82ð\89ð\90Í\82·\82é}
2103 function TREParser.Primary: REpNode_t;
2104 begin
2105   case FScanner.Token of
2106     retk_Char: begin
2107         result := FParseTree.MakeLeaf(FScanner.Symbol.WChar, FScanner.Symbol.WChar);
2108         FScanner.GetToken;
2109       end;
2110     retk_LHead: begin
2111         result := FParseTree.MakeLHeadNode(FScanner.Symbol.WChar);
2112         FScanner.GetToken;
2113       end;
2114     retk_LTail: begin
2115         result := FParseTree.MakeLTailNode(FScanner.Symbol.WChar);
2116         FScanner.GetToken;
2117       end;
2118     retk_Dot: begin
2119         result := FParseTree.MakeAnyCharsNode;
2120         FScanner.GetToken;
2121       end;
2122     retk_LPar: begin
2123         FScanner.GetToken;
2124         result := regexp;
2125         if FScanner.Token <> retk_RPar then
2126           raise ERegExpParser.Create('\89E(\95Â\82¶)\8a\87\8cÊ\82ª\95K\97v\82Å\82·', FScanner.Index);
2127         FScanner.GetToken;
2128       end;
2129     retk_LBra, retk_LBraNeg: begin
2130         if FScanner.Token = retk_LBra then
2131           result := CharacterClass(FParseTree)
2132         else
2133           result := NegativeCharacterClass;
2134         if FScanner.Token <> retk_RBra then
2135           raise ERegExpParser.Create('\89E\83u\83\89\83P\83b\83g"]"\82ª\95K\97v\82Å\82·', FScanner.Index);
2136         FScanner.GetToken;
2137       end;
2138     else
2139       raise ERegExpParser.Create('\95\81\92Ê\82Ì\95\8e\9a\81A\82Ü\82½\82Í\8d\8a\87\8cÊ"("\82ª\95K\97v\82Å\82·', FScanner.Index);
2140   end;
2141 end;
2142
2143 { <charclass> \82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
2144       [] \82Å\8a\87\82ç\82ê\82½\90³\8bK\95\\8c»\82ð\89ð\90Í\82·\82é}
2145 function TREParser.CharacterClass(aParseTree: TREParseTree): REpNode_t;
2146   {Token\82É\91Î\89\9e\82µ\82½\97t\82ð\8dì\82é}
2147   function WCharToLeaf: REpNode_t;
2148   begin
2149     result := nil;
2150     case FScanner.Token of
2151       retk_Char:
2152         result := aParseTree.MakeLeaf(FScanner.Symbol.WChar, FScanner.Symbol.WChar);
2153
2154       retk_CharClass:
2155         result := aParseTree.MakeLeaf(FScanner.Symbol.CharClass.StartChar,
2156                                       FScanner.Symbol.CharClass.EndChar);
2157     end;
2158   end;
2159 begin {function TREParser.CharacterClass}
2160   FScanner.GetToken; {GetScannerCC\82Í\81Aretk_RBra, retk_Char, retk_CharClass\82µ\82©\95Ô\82³\82È\82¢}
2161   if FScanner.Token = retk_RBra then
2162     raise ERegExpParser.Create('\95s\90³\82È\83L\83\83\83\89\83N\83^\83N\83\89\83X\8ew\92è\82Å\82·\81B', FScanner.Index);
2163
2164   result := WCharToLeaf;
2165   FScanner.GetToken;
2166   while FScanner.Token <> retk_RBra do begin
2167     result := aParseTree.MakeInternalNode(reop_Union, result, WCharToLeaf);
2168     FScanner.GetToken;
2169   end;
2170
2171 end;{function TREParser.CharacterClass}
2172
2173
2174 { <negative charclass>\82ð\83p\81[\83X\82µ\82Ä\81A\93¾\82ç\82ê\82½\8d\\95\96Ø\82ð\95Ô\82·\81B
2175   [^ ] \82Å\8a\87\82ç\82ê\82½\90³\8bK\95\\8c»\82ð\89ð\90Í\82·\82é}
2176 function TREParser.NegativeCharacterClass: REpNode_t;
2177 var
2178   aParseTree, aNeg_ParseTree: TREParseTree;
2179   i: Integer;
2180   aCharClass: RECharClass_t;
2181   procedure RemoveCC(pLeaf: REpNode_t);
2182   var
2183     i: Integer;
2184     pANode, pNode1, pNode2: REpNode_t;
2185   begin
2186     i := 0;
2187     while i < aNeg_ParseTree.LeafList.Count do begin
2188       pANode := aNeg_ParseTree.LeafList[i];
2189       if (pLeaf^.CharClass.EndChar < pANode^.CharClass.StartChar) or
2190       (pLeaf^.CharClass.StartChar > pANode^.CharClass.EndChar) then
2191         Inc(i)
2192       else begin
2193         pNode1 := aNeg_ParseTree.Check_and_MakeLeaf(pANode^.CharClass.StartChar,
2194           pLeaf^.CharClass.StartChar-1);
2195         pNode2 := aNeg_ParseTree.Check_and_MakeLeaf(pLeaf^.CharClass.EndChar+1,
2196           pANode^.CharClass.EndChar);
2197         if (pNode1 <> nil) or (pNode2 <> nil) then begin
2198           Dispose(REpNode_t(aNeg_ParseTree.LeafList[i]));
2199           aNeg_ParseTree.LeafList.Delete(i);
2200 //======== 2015/01/07 mod zako ========
2201         end else begin
2202           Inc(i);
2203 //======== 2015/01/07 mod zako ========
2204         end;
2205       end;
2206     end;
2207   end;
2208 begin
2209 { [^abc] = . - [abc] \82Æ\82¢\82¤\93®\8dì\82ð\82·\82é\81B}
2210
2211   aParseTree := TREParseTree.Create;
2212   try
2213   aNeg_ParseTree := TREParseTree.Create;
2214   try
2215     {aParseTree\82É'[]'\82Å\88Í\82Ü\82ê\82½\83L\83\83\83\89\83N\83^\83N\83\89\83X\90³\8bK\95\\8c»\82Ì\92\86\82É\91Î\89\9e\82·\82é\90ß\82ð\8dì\82é\81B}
2216     aParseTree.pHeadNode := CharacterClass(aParseTree);
2217     {aParseTree\82Ì\97t\82ª\8e\9d\82Â\83L\83\83\83\89\83N\83^\83N\83\89\83X\82Ì\94Í\88Í\82ª\8fd\95¡\82µ\82È\82¢\82æ\82¤\82É\90®\8c`}
2218     aParseTree.ForceCharClassUnique;
2219
2220     {\94C\88Ó\82Ì\88ê\95\8e\9a\82ð\95\\82·\96Ø\82ðaNeg_ParseTree\82É\8dì\90¬}
2221     aNeg_ParseTree.MakeAnyCharsNode;
2222
2223     for i := 0 to aParseTree.LeafList.Count-1 do begin
2224       {aNeg_ParseTree\82Ì\97t\82©\82çaParseTree\82Ì\97t\82Æ\93¯\82\95¨\82ð\8dí\8f\9c}
2225       RemoveCC(aParseTree.LeafList[i]);
2226     end;
2227
2228     {aNeg_ParseTree\82Ì\97t\82ðFParseTree\82É\83R\83s\81[}
2229     result := nil;
2230     if aNeg_ParseTree.LeafList.Count > 0 then begin
2231       aCharClass := REpNode_t(aNeg_ParseTree.LeafList[0])^.CharClass;
2232       result := FParseTree.MakeLeaf(aCharClass.StartChar, aCharClass.EndChar);
2233       for i := 1 to aNeg_ParseTree.LeafList.Count-1 do begin
2234         aCharClass := REpNode_t(aNeg_ParseTree.LeafList[i])^.CharClass;
2235         result := FParseTree.MakeInternalNode(reop_Union, result,
2236           FParseTree.MakeLeaf(aCharClass.StartChar, aCharClass.EndChar));
2237       end;
2238     end;
2239   finally
2240     aNeg_ParseTree.Free;
2241   end;
2242   finally
2243     aParseTree.Free;
2244   end;
2245 end;
2246
2247 {$IFDEF DEBUG}
2248 function DebugWCharToStr(WChar: WChar_t): String;
2249 begin
2250   if WChar > $FF then
2251     result := ' ' + Chr(Hi(WChar))+Chr(Lo(WChar))+'($' + IntToHex(WChar, 4) + ')'
2252   else
2253     result := ' ' + Chr(Lo(WChar))+' ($00' + IntToHex(WChar, 2) + ')';
2254
2255 end;
2256
2257\83f\83o\83b\83O\97p\83\81\83b\83\\83b\83h\81B\8d\\95\96Ø\82ðVCL \82ÌTOutLine\83R\83\93\83|\81[\83l\83\93\83g\82É\8f\91\82«\8d\9e\82Þ}
2258\8d\\95\96Ø\82ª\91å\82«\82·\82¬\82é\82Æ\81ATOutLine\83R\83\93\83|\81[\83l\83\93\83g\82ª\81h\8e\80\82Ê\81h\82Ì\82Å\92\8d\88Ó}
2259 procedure TREParser.WriteParseTreeToOutLine(anOutLine: TOutLine);
2260   procedure SetOutLineRecursive(pTree: REpNode_t; ParentIndex: Integer);
2261   var
2262     aStr: String;
2263     NextParentIndex: Integer;
2264   begin
2265     if pTree = nil then
2266       exit;
2267
2268     case pTree^.op of
2269       reop_Char: begin{ \95\8e\9a\82»\82Ì\82à\82Ì }
2270           if pTree^.CharClass.StartChar <> pTree^.CharClass.EndChar then
2271             aStr := DebugWCharToStr(pTree^.CharClass.StartChar)
2272             + ' \81` '+ DebugWCharToStr(pTree^.CharClass.EndChar)
2273           else
2274             aStr := DebugWCharToStr(pTree^.CharClass.StartChar);
2275         end;
2276       reop_LHead:
2277           aStr := '\95\93ª '+DebugWCharToStr(pTree^.CharClass.StartChar);
2278       reop_LTail:
2279           aStr := '\95\94ö '+DebugWCharToStr(pTree^.CharClass.StartChar);
2280       reop_Concat:{ XY }
2281           aStr := '\98A\8c\8b ';
2282       reop_Union:{ X|Y}
2283           aStr := '\91I\91ð "|"';
2284       reop_Closure:{ X* }
2285           aStr := '\95Â\95ï "*"';
2286       reop_Empty:{ \8bó }
2287           aStr := '\8bó';
2288     end;
2289
2290     NextParentIndex := anOutLine.AddChild(ParentIndex, aStr);
2291
2292     if pTree^.op in [reop_Concat, reop_Union, reop_Closure] then begin
2293       SetOutLineRecursive(pTree^.Children.pLeft, NextParentIndex);
2294       SetOutLineRecursive(pTree^.Children.pRight, NextParentIndex);
2295     end;
2296   end;
2297 begin
2298   anOutLine.Clear;
2299   SetOutLineRecursive(FParseTree.pHeadNode, 0);
2300 end;
2301
2302 {$ENDIF}
2303
2304 { -============================== TRE_NFA Class ==================================-}
2305 constructor TRE_NFA.Create(Parser: TREParser; LHeadWChar, LTailWChar: WChar_t);
2306 begin
2307   inherited Create;
2308   FStateList := TList.Create;
2309   FParser := Parser;
2310   FLHeadWChar := LHeadWChar;
2311   FLTailWChar := LTailWChar;
2312 end;
2313
2314 destructor TRE_NFA.Destroy;
2315 begin
2316   DisposeStateList;
2317   inherited Destroy;
2318 end;
2319
2320 { NFA\8fó\91Ô\95\\82ð\94j\8aü\82·\82é}
2321 procedure TRE_NFA.DisposeStateList;
2322 var
2323   i: Integer;
2324   pNFANode, pNext: RE_pNFANode_t;
2325 begin
2326   if FStateList <> nil then begin
2327     for i := 0 to FStateList.Count-1 do begin
2328       pNFANode := FStateList.Items[i];
2329       while pNFANode <> nil do begin
2330         pNext := pNFANode^.Next;
2331         Dispose(pNFANode);
2332         pNFANode := pNext;
2333       end;
2334     end;
2335     FStateList.Free;
2336     FStateList := nil;
2337   end;
2338 end;
2339
2340\8d\\95\96Ø Tree\82É\91Î\89\9e\82·\82éNFA\82ð\90\90¬\82·\82é}
2341 procedure TRE_NFA.Run;
2342 begin
2343   { NFA \82Ì\8f\89\8aú\8fó\91Ô\82Ì\83m\81[\83h\82ð\8a\84\82è\93\96\82Ä\82é\81B}
2344   FEntryState := NumberNode;
2345
2346   { NFA \82Ì\8fI\97¹\8fó\91Ô\82Ì\83m\81[\83h\82ð\8a\84\82è\93\96\82Ä\82é }
2347   FExitState := NumberNode;
2348
2349   { NFA \82ð\90\90¬\82·\82é }
2350   GenerateStateList(FParser.ParseTree.pHeadNode, FEntryState, FExitState);
2351 end;
2352
2353\83m\81[\83h\82É\94Ô\8d\86\82ð\8a\84\82è\93\96\82Ä\82é}
2354 function TRE_NFA.NumberNode: Integer;
2355 begin
2356   with FStateList do begin
2357     result := Add(nil);
2358   end;
2359 end;
2360
2361 { NFA\8fó\91Ô\90ß \82ð\82P\82Â\8dì\90¬}
2362 function TRE_NFA.MakeNFANode: RE_pNFANode_t;
2363 begin
2364   New(result);
2365 end;
2366
2367 { FStateList\82É\8fó\91Ô\91J\88Ú\82ð\92Ç\89Á\82·\82é\81B
2368   \8fó\91Ô TransFrom \82É\91Î\82µ\82Ä aCharClass\93à\82Ì\95\8e\9a\82Å\8fó\91Ô TransTo \82Ö\82Ì\91J\88Ú\82ð\92Ç\89Á\82·\82é\81B}
2369 procedure TRE_NFA.AddTransition(TransFrom, TransTo: Integer;
2370   aCharClass: RECharClass_t); {Char}
2371 var
2372   pNFANode: RE_pNFANode_t;
2373 begin
2374   pNFANode := MakeNFANode;
2375
2376   with pNFANode^ do begin
2377     CharClass := aCharClass;
2378     TransitTo := TransTo;
2379     Next := RE_pNFANode_t(FStateList.Items[TransFrom]);
2380   end;
2381   FStateList.Items[TransFrom] := pNFANode;
2382 end;
2383
2384\8d\\95\96Ø pTree \82É\91Î\82·\82é StateList\82ð\90\90¬\82·\82é
2385   NFA\82Ì\93ü\82è\8cû\82ðentry, \8fo\8cû\82ðway_out\82Æ\82·\82é }
2386 procedure TRE_NFA.GenerateStateList(pTree: REpNode_t; entry, way_out: Integer);
2387 var
2388   aState1, aState2: Integer;
2389   aCharClass: RECharClass_t;
2390 begin
2391   case pTree^.op of
2392     reop_Char:
2393         AddTransition(entry, way_out, pTree^.CharClass);
2394     reop_LHead: begin {'^'}
2395         {\95\93ª\83\81\83^\83L\83\83\83\89\83N\83^'^' \82Í TransFrom = FEntryState\82Ì\82Æ\82«\88È\8aO\82Í\81A
2396          \92Ê\8fí\82Ì\83L\83\83\83\89\83N\83^\82Æ\82µ\82Ä\88µ\82¤\81B}
2397         if Entry <> FEntryState then begin
2398           AddTransition(entry, way_out, pTree^.CharClass);
2399         end else begin
2400           FRegExpHasLHead := True;
2401           with aCharClass do begin
2402             StartChar := FLHeadWChar;
2403             EndChar := FLHeadWChar;
2404           end;
2405           AddTransition(entry, way_out, aCharClass);
2406         end;
2407       end;
2408     reop_LTail: begin
2409         {\8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^ '$'\82Í\81ATransTo = FExitState\82Ì\82Æ\82«\88È\8aO\82Í\81A
2410         \92Ê\8fí\82Ì\83L\83\83\83\89\83N\83^\82Æ\82µ\82Ä\88µ\82¤\81B}
2411         if way_out <> FExitState then begin
2412           AddTransition(entry, way_out, pTree^.CharClass);
2413         end else begin
2414           FRegExpHasLTail := True;
2415           with aCharClass do begin
2416             StartChar := FLTailWChar;
2417             EndChar := FLTailWChar;
2418           end;
2419           AddTransition(entry, way_out, aCharClass);
2420         end;
2421       end;
2422     reop_Union: begin  {'|'}
2423         GenerateStateList(pTree^.Children.pLeft, entry, way_out);
2424         GenerateStateList(pTree^.Children.pRight, entry, way_out);
2425       end;
2426     reop_Closure: begin {'*'}
2427         aState1 := NumberNode;
2428         aState2 := NumberNode;
2429         { \8fó\91Ô entry \81¨ \83Ã\91J\88Ú \81¨ \8fó\91Ô aState1}
2430         AddTransition(entry, aState1, CONST_EMPTYCharClass);
2431         { \8fó\91Ô aState1 \81¨ (pTree^.Children.pLeft)\88È\89º\82Ì\91J\88Ú \81¨ \8fó\91Ô aState2}
2432         GenerateStateList(pTree^.Children.pLeft, aState1, aState2);
2433         { \8fó\91Ô aState2 \81¨ \83Ã\91J\88Ú \81¨ \8fó\91Ô aState1}
2434         AddTransition(aState2, aState1, CONST_EMPTYCharClass);
2435         { \8fó\91Ô aState1 \81¨ \83Ã\91J\88Ú \81¨ \8fó\91Ô way_out}
2436         AddTransition(aState1, way_out, CONST_EMPTYCharClass);
2437       end;
2438     reop_Concat: begin {'AB'}
2439         aState1 := NumberNode;
2440         { \8fó\91Ô entry \81¨ (pTree^.Children.pLeft)\91J\88Ú \81¨ \8fó\91Ô aState1}
2441         GenerateStateList(pTree^.Children.pLeft, entry, aState1);
2442         { \8fó\91Ô aState1 \81¨ (pTree^.Children.pRight)\91J\88Ú \81¨ \8fó\91Ô way_out}
2443         GenerateStateList(pTree^.Children.pRight, aState1, way_out);
2444       end;
2445     reop_Empty:
2446         AddTransition(entry, way_out, CONST_EMPTYCharClass);
2447     else begin
2448         raise Exception.Create('This cannot happen in TRE_NFA.GenerateStateList');
2449       end;
2450   end;
2451 end;
2452
2453 {$IFDEF DEBUG}
2454 {TStrings\83I\83u\83W\83F\83N\83g\82É\81ANFA \82Ì\93à\97e\82ð\8f\91\82«\8d\9e\82Þ}
2455 procedure TRE_NFA.WriteNFAtoStrings(Strings: TStrings);
2456 var
2457   i: Integer;
2458   pNFANode: RE_pNFANode_t;
2459   Str: String;
2460 begin
2461   Strings.clear;
2462   Strings.BeginUpDate;
2463   for i := 0 to FStateList.Count-1 do begin
2464     pNFANode := FStateList.items[i];
2465     if i = EntryState then
2466       Str := Format('\8aJ\8en %2d : ', [i])
2467     else if i = ExitState then
2468       Str := Format('\8fI\97¹ %2d : ', [i])
2469     else
2470       Str := Format('\8fó\91Ô %2d : ', [i]);
2471     while pNFANode <> nil do begin
2472       if pNFANode^.CharClass.StartChar = CONST_EMPTY then
2473         Str := Str + Format('\83Ã\91J\88Ú\82Å \8fó\91Ô %2d \82Ö :',[pNFANode^.TransitTo])
2474       else if pNFANode^.CharClass.StartChar <> pNFANode^.CharClass.EndChar then
2475         Str := Str + Format('\95\8e\9a%s \82©\82ç%s \82Å \8fó\91Ô %2d \82Ö :',
2476           [DebugWCharToStr(pNFANode^.CharClass.StartChar),
2477           DebugWCharToStr(pNFANode^.CharClass.EndChar), pNFANode^.TransitTo])
2478       else if pNFANode^.CharClass.StartChar = FLHeadWChar then begin
2479         Str := Str + Format('\95\93ª\83R\81[\83h%s \82Å \8fó\91Ô %2d \82Ö :',
2480           [DebugWCharToStr(pNFANode^.CharClass.StartChar), pNFANode^.TransitTo]);
2481       end else if pNFANode^.CharClass.StartChar = FLTailWChar then begin
2482         Str := Str + Format('\95\94ö\83R\81[\83h%s \82Å \8fó\91Ô %2d \82Ö :',
2483           [DebugWCharToStr(pNFANode^.CharClass.StartChar), pNFANode^.TransitTo]);
2484       end else
2485         Str := Str + Format('\95\8e\9a%s \82Å \8fó\91Ô %2d \82Ö :',
2486           [DebugWCharToStr(pNFANode^.CharClass.StartChar), pNFANode^.TransitTo]);
2487
2488       pNFANode := pNFANode^.Next;
2489     end;
2490     Strings.Add(Str);
2491   end;
2492   Strings.EndUpDate;
2493 end;
2494 {$ENDIF}
2495
2496 { -========================== TRE_NFAStateSet Class =============================-}
2497 constructor TRE_NFAStateSet.Create(StateMax: Integer);
2498 var
2499   i: Integer;
2500 begin
2501   inherited Create;
2502   FCapacity := StateMax div 8 + 1;
2503   GetMem(FpArray, FCapacity);
2504   for i := 0 to FCapacity-1 do
2505     FpArray^[i] := 0;
2506 end;
2507
2508 destructor TRE_NFAStateSet.Destroy;
2509 begin
2510   FreeMem(FpArray, FCapacity);
2511   inherited Destroy;
2512 end;
2513
2514 function TRE_NFAStateSet.Has(StateIndex: Integer): Boolean;
2515 begin
2516   result := (FpArray^[StateIndex div 8] and (1 shl (StateIndex mod 8))) <> 0;
2517 end;
2518
2519 procedure TRE_NFAStateSet.Include(StateIndex: Integer);
2520 begin
2521   FpArray^[StateIndex div 8] := FpArray^[StateIndex div 8] or
2522     (1 shl (StateIndex mod 8));
2523 end;
2524
2525 function TRE_NFAStateSet.Equals(AStateSet: TRE_NFAStateSet): Boolean;
2526 var
2527   i: Integer;
2528 begin
2529   result := False;
2530   for i := 0 to FCapacity - 1 do begin
2531     if FpArray^[i] <> AStateSet.pArray^[i] then
2532       exit;
2533   end;
2534   result := True;
2535 end;
2536
2537 { -============================= TRE_DFA Class ==================================-}
2538 constructor TRE_DFA.Create(NFA: TRE_NFA);
2539 begin
2540   inherited Create;
2541   FNFA := NFA;
2542   FStateList := TList.Create;
2543 end;
2544
2545 destructor TRE_DFA.Destroy;
2546 begin
2547   DestroyStateList;
2548
2549   inherited Destroy;
2550 end;
2551
2552 {DFA\8fó\91Ô\82Ì\83\8a\83X\83g\82ð\94j\8aü}
2553 procedure TRE_DFA.DestroyStateList;
2554 var
2555   i: Integer;
2556   pDFA_State: RE_pDFAState_t;
2557   pDFA_StateSub, pNextSub: RE_pDFAStateSub_t;
2558 begin
2559   if FStateList <> nil then begin
2560     for i := 0 to FStateList.Count-1 do begin
2561       pDFA_State := FStateList.Items[i];
2562       if pDFA_State <> nil then begin
2563         pDFA_StateSub := pDFA_State^.next;
2564         while pDFA_StateSub <> nil do begin
2565           pNextSub := pDFA_StateSub^.next;
2566           Dispose(pDFA_StateSub);
2567           pDFA_StateSub := pNextSub;
2568         end;
2569         pDFA_State^.StateSet.Free;
2570         Dispose(pDFA_State);
2571       end;
2572     end;
2573     FStateList.Free;
2574     FStateList := nil;
2575   end;
2576 end;
2577
2578 procedure TRE_DFA.Run;
2579 begin
2580   FRegExpHasLHead := FNFA.RegExpHasLHead;
2581   FRegExpHasLTail := FNFA.RegExpHasLTail;
2582   Convert_NFA_to_DFA;   {NFA\8fó\91Ô\95\\82©\82çDFA\8fó\91Ô\95\\82ð\8dì\82é}
2583   StateListSort;        {DFA\8fó\91Ô\95\\82Ì\90ß\82ð\93ü\97Í\83L\81[\8f\87\82É\90®\97ñ\82·\82é\81B\81¦\8c\9f\8dõ\82Ì\8d\82\91¬\89»\82Ì\82½\82ß}
2584   CheckIfRegExpIsSimple;{\90³\8bK\95\\8c»\82ª\92P\8f\83\82È\95\8e\9a\97ñ\82©\83`\83F\83b\83N}
2585 end;
2586
2587 { NFA\82ð\93\99\89¿\82È\82c\82e\82`\82Ö\82Æ\95Ï\8a·\82·\82é}
2588 procedure TRE_DFA.Convert_NFA_to_DFA;
2589 var
2590   Initial_StateSet: TRE_NFAStateSet;
2591   t: RE_pDFAState_t;
2592   pDFA_TransNode, pTransNodeHead: RE_pDFATransNode_t;
2593   pDFA_StateSub: RE_pDFAStateSub_t;
2594 begin
2595 {DFA\82Ì\8f\89\8aú\8fó\91Ô\82ð\93o\98^\82·\82é}
2596   Initial_StateSet := TRE_NFAStateSet.Create(FNFA.StateList.Count);
2597   Initial_StateSet.Include(FNFA.EntryState);
2598   {\82m\82e\82`\8f\89\8aú\8fó\91Ô\82Ì\8fW\8d\87\82ð\8b\81\82ß\82é\81i\83Ã\91J\88Ú\82à\8aÜ\82Þ\81j}
2599   Collect_Empty_Transition(Initial_StateSet);
2600   FpInitialState := Register_DFA_State(Initial_StateSet);
2601
2602   {\96¢\8f\88\97\9d\82Ì\82c\82e\82`\8fó\91Ô\82ª\82 \82ê\82Î\81A\82»\82ê\82ð\8eæ\82è\8fo\82µ\82Ä\8f\88\97\9d\82·\82é
2603     \92\8d\96Ú\82µ\82Ä\82¢\82é\82c\82e\82`\8fó\91Ô\82ð\82\94\82Æ\82·\82é}
2604   t := Fetch_Unvisited_D_state;
2605   while t <> nil do begin
2606
2607     {\8f\88\97\9d\8dÏ\82Ý\82Ì\88ó\82ð\95t\82¯\82é}
2608     t^.visited := True;
2609
2610     {\8fó\91Ô\82\94\82©\82ç\91J\88Ú\89Â\94\\82ÈDFA\8fó\91Ô\82ð\82·\82×\82ÄDFA\82É\93o\98^\82·\82é\81B}
2611     pTransNodeHead := Compute_Reachable_N_state(t);
2612     try
2613     pDFA_TransNode := pTransNodeHead;
2614     while pDFA_TransNode <> nil do begin
2615       { NFA\8fó\91Ô\8fW\8d\87\82Ì\83Ã-closure\82ð\8b\81\82ß\82é}
2616       Collect_Empty_Transition(pDFA_TransNode^.ToNFAStateSet);
2617
2618       { \91J\88Ú\8fî\95ñ\82ðDFA\8fó\91Ô\82É\89Á\82¦\82é}
2619       New(pDFA_StateSub);
2620       with pDFA_StateSub^ do begin
2621         next := nil;
2622         CharClass := pDFA_TransNode^.CharClass;
2623         next := t^.next;
2624       end;
2625       t^.next := pDFA_StateSub;
2626
2627       {\8c»\8dÝ\82ÌDFA\8fó\91Ô\82©\82ç\82Ì\91J\88Ú\90æ\82Ì\90V\82µ\82¢DFA\8fó\91Ô\82ð\93o\98^}
2628       pDFA_StateSub^.TransitTo :=
2629         Register_DFA_State(pDFA_TransNode^.ToNFAStateSet);
2630       {Register_DFA_State\83\81\83\\83b\83h\82É\82æ\82èToNFAStateSet\83I\83u\83W\83F\83N\83g\82ÍDFA_State\82É\8f\8a\97L\82³\82ê\82é}
2631       {pDFA_TransNode^.ToNFAStateSet := nil;}
2632
2633       pDFA_TransNode := pDFA_TransNode^.next;
2634     end;
2635     t := Fetch_Unvisited_D_state;
2636     finally
2637       Destroy_DFA_TransList(pTransNodeHead);
2638     end;
2639   end;
2640 end;
2641
2642 { NFA\8fó\91Ô\8fW\8d\87 StateSet \82É\91Î\82µ\82Ä \83Ã-closure\91\80\8dì\82ð\8eÀ\8ds\82·\82é\81B
2643   \83Ã\91J\88Ú\82Å\91J\88Ú\89Â\94\\82È\91S\82Ä\82Ì\82m\82e\82`\8fó\91Ô\82ð\92Ç\89Á\82·\82é}
2644 procedure TRE_DFA.Collect_Empty_Transition(StateSet: TRE_NFAStateSet);
2645 var
2646   i: Integer;
2647   { NFA\8fó\91Ô\8fW\8d\87 StateSet\82É\82m\82e\82`\8fó\91Ô \82\93\82ð\92Ç\89Á\82·\82é\81B
2648     \93¯\8e\9e\82É\82m\82e\82`\8fó\91Ô\82\93\82©\82ç\83Ã\91J\88Ú\82Å\88Ú\93®\82Å\82«\82é\82m\82e\82`\8fó\91Ô\82à\92Ç\89Á\82·\82é}
2649   procedure Mark_Empty_Transition(StateSet: TRE_NFAStateSet; s: Integer);
2650   var
2651     pNFANode: RE_pNFANode_t;
2652   begin
2653     StateSet.Include(s);
2654     pNFANode := FNFA.StateList[s];
2655     while pNFANode <> nil do begin
2656       if (pNFANode^.CharClass.StartChar = CONST_EMPTY) and
2657         (not StateSet.Has(pNFANode^.TransitTo)) then
2658         Mark_Empty_Transition(StateSet, pNFANode^.TransitTo);
2659       pNFANode := pNFANode^.next;
2660     end;
2661   end;
2662 begin
2663   for i := 0 to FNFA.StateList.Count-1 do begin
2664     if StateSet.Has(i) then
2665       Mark_Empty_Transition(StateSet, i);
2666   end;
2667 end;
2668
2669 { NFA\8fó\91Ô\8fW\8d\87 aStateSet \82ð\82c\82e\82`\82É\93o\98^\82µ\82Ä\81A\82c\82e\82`\8fó\91Ô\82Ö\82Ì\83|\83C\83\93\83^\82ð\95Ô\82·\81B
2670   aStateSet\82ª\8fI\97¹\8fó\91Ô\82ð\8aÜ\82ñ\82Å\82¢\82ê\82Î\81Aaccepted\83t\83\89\83O\82ð\83Z\83b\83g\82·\82é\81B
2671   \82·\82Å\82ÉaStateSet\82ª\82c\82e\82`\82É\93o\98^\82³\82ê\82Ä\82¢\82½\82ç\89½\82à\82µ\82È\82¢}
2672 function TRE_DFA.Register_DFA_State(var aStateSet: TRE_NFAStateSet): RE_pDFAState_t;
2673 var
2674   i: Integer;
2675 begin
2676   { NFA\8fó\91Ô aStateSet \82ª\82·\82Å\82É\82c\82e\82`\82É\93o\98^\82³\82ê\82Ä\82¢\82½\82ç\81A\89½\82à\82µ\82È\82¢\82Å\83\8a\83^\81[\83\93\82·\82é}
2677   for i := 0 to FStateList.Count-1 do begin
2678     if RE_pDFAState_t(FStateList[i])^.StateSet.Equals(aStateSet) then begin
2679       result := RE_pDFAState_t(FStateList[i]);
2680       exit;
2681     end;
2682   end;
2683
2684   {DFA\82É\95K\97v\82È\8fî\95ñ\82ð\83Z\83b\83g\82·\82é}
2685   New(result);
2686   with result^ do begin
2687     StateSet := aStateSet;
2688     visited := False;
2689     if aStateSet.Has(FNFA.ExitState) then
2690       accepted := True
2691     else
2692       accepted := False;
2693     next := nil;
2694   end;
2695   aStateSet := nil;
2696   FStateList.add(result);
2697 end;
2698
2699\8f\88\97\9d\8dÏ\82Ý\82Ì\88ó\82ª\82Â\82¢\82Ä\82¢\82È\82¢\82c\82e\82`\8fó\91Ô\82ð\92T\82·\81B
2700   \8c©\82Â\82©\82ç\82È\82¯\82ê\82Înil\82ð\95Ô\82·\81B}
2701 function TRE_DFA.Fetch_Unvisited_D_state: RE_pDFAState_t;
2702 var
2703   i: Integer;
2704 begin
2705
2706   for i := 0 to FStateList.Count-1 do begin
2707     if not RE_pDFAState_t(FStateList[i])^.visited then begin
2708       result := FStateList[i];
2709       exit;
2710     end;
2711   end;
2712   result := nil;
2713 end;
2714
2715 {Compute_Reachable_N_state \82ª\8dì\82é RE_DFATransNode_t\8c^\82Ì\83\8a\83\93\83N\83\8a\83X\83g\82ð\94j\8aü\82·\82é}
2716 procedure TRE_DFA.Destroy_DFA_TransList(pDFA_TransNode: RE_pDFATransNode_t);
2717 var
2718   pNext: RE_pDFATransNode_t;
2719 begin
2720   if pDFA_TransNode <> nil then begin
2721     while pDFA_TransNode <> nil do begin
2722       pNext := pDFA_TransNode^.next;
2723       if pDFA_TransNode^.ToNFAStateSet <> nil then
2724         pDFA_TransNode^.ToNFAStateSet.Free;
2725       Dispose(pDFA_TransNode);
2726
2727       pDFA_TransNode := pNext;
2728     end;
2729   end;
2730 end;
2731
2732 { DFA\8fó\91ÔpDFAState\82©\82ç\91J\88Ú\89Â\94\\82ÈNFA\8fó\91Ô\82ð\92T\82µ\82Ä\81A\83\8a\83\93\83N\83\8a\83X\83g\82É\82µ\82Ä\95Ô\82·}
2733 function TRE_DFA.Compute_Reachable_N_state(pDFAState: RE_pDFAState_t): RE_pDFATransNode_t;
2734 var
2735   i: Integer;
2736   pNFANode: RE_pNFANode_t;
2737   a, b: RE_pDFATransNode_t;
2738 label
2739   added;
2740 begin
2741   result := nil;
2742 try
2743   {\82·\82×\82Ä\82Ì\82m\82e\82`\8fó\91Ô\82ð\8f\87\82É\92²\82×\82é}
2744   for i := 0 to FNFA.StateList.Count-1 do begin
2745
2746     { NFA\8fó\91Ôi\82ªDFA\8fó\91Ô pDFAState\82É\8aÜ\82Ü\82ê\82Ä\82¢\82ê\82Î\81A\88È\89º\82Ì\8f\88\97\9d\82ð\8ds\82¤}
2747     if pDFAState^.StateSet.Has(i) then begin
2748
2749       { NFA\8fó\91Ô i \82©\82ç\91J\88Ú\89Â\94\\82È\82m\82e\82`\8fó\91Ô\82ð\82·\82×\82Ä\92²\82×\82Ä\83\8a\83X\83g\82É\82·\82é}
2750       pNFANode := RE_pNFANode_t(FNFA.StateList[i]);
2751       while pNFANode <> nil do begin
2752         if pNFANode^.CharClass.StartChar <> CONST_EMPTY then begin {\83Ã\91J\88Ú\82Í\96³\8e\8b}
2753           a := result;
2754           while a <> nil do begin
2755             if a^.CharClass.Chars = pNFANode^.CharClass.Chars then begin
2756               a^.ToNFAStateSet.Include(pNFANode^.TransitTo);
2757               goto added;
2758             end;
2759             a := a^.next;
2760           end;
2761           {\83L\83\83\83\89\83N\83^ pNFANode^.CharClass.c\82É\82æ\82é\91J\88Ú\82ª\93o\98^\82³\82ê\82Ä\82¢\82È\82¯\82ê\82Î\92Ç\89Á}
2762           New(b);
2763           with b^ do begin
2764             CharClass := pNFANode^.CharClass;
2765             ToNFAStateSet := TRE_NFAStateSet.Create(FNFA.StateList.Count);
2766             ToNFAStateSet.Include(pNFANode^.TransitTo);
2767             next := result;
2768           end;
2769           result := b;
2770         added:
2771           ;
2772         end;
2773         pNFANode := pNFANode^.next;
2774       end;
2775     end;
2776   end;
2777 except
2778   on EOutOfMemory do begin
2779     Destroy_DFA_TransList(result); {\8d\\92z\92\86\82Ì\83\8a\83X\83g\94p\8aü}
2780     raise;
2781   end;
2782 end;
2783 end;
2784
2785 {\8fó\91Ô\83\8a\83X\83g\82Ì\83\8a\83\93\83N\83\8a\83X\83g\82ð\90®\97ñ\82·\82é(\83}\81[\83W\81E\83\\81[\83g\82ð\8eg\97p)}
2786 procedure TRE_DFA.StateListSort;
2787 var
2788   i: Integer;
2789   {\83}\81[\83W\81E\83\\81[\83g\8f\88\97\9d\82ð\8dÄ\8bA\93I\82É\8ds\82¤}
2790   function DoSort(pCell: RE_pDFAStateSub_t): RE_pDFAStateSub_t;
2791   var
2792     pMidCell, pACell: RE_pDFAStateSub_t;
2793
2794     {2\82Â\82Ì\83\8a\83X\83g\82ð\83\\81[\83g\82µ\82È\82ª\82ç\95¹\8d\87\82·\82é}
2795     function MergeList(pCell1, pCell2: RE_pDFAStateSub_t): RE_pDFAStateSub_t;
2796     var
2797       Dummy: RE_DFAStateSub_t;
2798     begin
2799       Result := @Dummy;
2800       {\82Ç\82¿\82ç\82©\82Ì\83\8a\83X\83g\82ª\81A\8bó\82É\82È\82é\82Ü\82Å\94½\95\9c}
2801       while (pCell1 <> nil) and (pCell2 <> nil) do begin
2802         {pCell1 \82Æ pCell2 \82ð\94ä\8ar\82µ\82Ä\8f¬\82³\82¢\95û\82ðResult\82É\92Ç\89Á\82µ\82Ä\82¢\82­}
2803         if pCell1^.CharClass.StartChar > pCell2^.CharClass.StartChar then begin
2804         {pCell2\82Ì\95û\82ª\8f¬\82³\82¢}
2805           Result^.Next := pCell2;
2806           Result := pCell2;
2807           pCell2 := pCell2^.Next;
2808         end else begin
2809         {pCell1\82Ì\95û\82ª\8f¬\82³\82¢}
2810           Result^.Next := pCell1;
2811           Result := pCell1;
2812           pCell1 := pCell1^.Next;
2813         end;
2814       end;
2815       {\97]\82Á\82½\83\8a\83X\83g\82ð\82»\82Ì\82Ü\82Üresult \82É\92Ç\89Á}
2816       if pCell1 = nil then
2817         Result^.Next := pCell2
2818       else
2819         Result^.Next := pCell1;
2820
2821       result := Dummy.Next;
2822     end;
2823
2824   {DoSort\96{\91Ì}
2825   begin
2826     if (pCell = nil) or (pCell^.Next = nil) then begin
2827       result := pCell;
2828       exit; {\97v\91f\82ª\82P\82Â\81A\82Ü\82½\82Í\81A\96³\82¢\82Æ\82«\82Í\81A\82·\82®\82É exit}
2829     end;
2830
2831     {ACell \82ª\82R\94Ô\96Ú\82Ì\83Z\83\8b\82ð\8ew\82·\82æ\82¤\82É\82·\82é\81B\96³\82¯\82ê\82Î\81Anil \82ð\8e\9d\82½\82¹\82é}
2832     {\83\8a\83X\83g\82ª\82Q\81`\82R\8cÂ\82Ì\83Z\83\8b\82ð\8e\9d\82Â\82Æ\82«\82É\82à\81A\95ª\8a\84\82ð\8ds\82¤\82æ\82¤\82É\82·\82é\81B}
2833     pACell := pCell^.Next^.Next;
2834     pMidCell := pCell;
2835     {MidCell \82ª\81A\83\8a\83X\83g\82Ì\90^\82ñ\92\86\82 \82½\82è\82Ì\83Z\83\8b\82ð\8ew\82·\82æ\82¤\82É\82·\82é\81B}
2836     while pACell <> nil do begin
2837       pMidCell := pMidCell^.Next;
2838       pACell := pACell^.Next;
2839       if pACell <> nil then
2840         pACell := pACell^.Next;
2841     end;
2842
2843     {MidCell \82Ì\8cã\82ë\82Å\83\8a\83X\83g\82ð\82Q\95ª\8a\84\82·\82é}
2844     pACell := pMidCell^.Next;
2845     pMidCell^.Next := nil;
2846
2847     result := MergeList(DoSort(pCell), DoSort(pACell));
2848   end;
2849 begin {Sort \96{\91Ì}
2850   for i := 0 to FStateList.Count-1 do begin
2851     RE_pDFAState_t(FStateList[i])^.next :=
2852       DoSort(RE_pDFAState_t(FStateList[i])^.next);
2853   end;
2854 end;
2855
2856 {\8b@\94\\81\8c»\8dÝ\82Ì\90³\8bK\95\\8c»\82ª\81A\95\81\92Ê\82Ì\95\8e\9a\97ñ\82©\81H
2857         \95\81\92Ê\82Ì\95\8e\9a\97ñ\82¾\82Á\82½\82ç\81AFRegExpIsSimple = True; FSimpleRegExpStr\82É\95\8e\9a\97ñ\82É\90Ý\92è
2858         \82»\82ê\88È\8aO\82Ì\8fê\8d\87\82Í\81A    FRegExpIsSimple = False;FSimpleRegExpStr = ''}
2859 procedure TRE_DFA.CheckIfRegExpIsSimple;
2860 var
2861   pDFAState: RE_pDFAState_t;
2862   pSub: RE_pDFAStateSub_t;
2863   WChar: WChar_t;
2864 begin
2865   FRegExpIsSimple := False;
2866   FSimpleRegExpStr := '';
2867
2868   pDFAState := FpInitialState;
2869
2870   while pDFAState <> nil do begin
2871     pSub := pDFAState^.next;
2872     if pSub = nil then
2873       break;
2874     if (pSub^.next <> nil) or
2875        {\95¡\90\94\82Ì\83L\83\83\83\89\83N\83^\82ð\8eó\82¯\93ü\82ê\82é}
2876       (pSub^.CharClass.StartChar <> pSub^.CharClass.EndChar) or
2877        {\83L\83\83\83\89\83N\83^\94Í\88Í\82ð\8e\9d\82Â}
2878       (pDFAState^.Accepted and (pSub^.TransitTo <> nil))
2879       {\8eó\97\9d\8cã\82à\83L\83\83\83\89\83N\83^\82ð\8eó\82¯\93ü\82ê\82é}then begin
2880
2881       FSimpleRegExpStr := '';
2882       exit;
2883     end else begin
2884       WChar := pSub^.CharClass.StartChar;
2885       FSimpleRegExpStr := FSimpleRegExpStr + WCharToStr(WChar);
2886     end;
2887     pDFAState := pSub^.TransitTo;
2888   end;
2889   FRegExpIsSimple := True;
2890 end;
2891
2892
2893 {$IFDEF DEBUG}
2894 {TStrings\83I\83u\83W\83F\83N\83g\82É\81ADFA \82Ì\93à\97e\82ð\8f\91\82«\8d\9e\82Þ}
2895 procedure TRE_DFA.WriteDFAtoStrings(Strings: TStrings);
2896 var
2897   i: Integer;
2898   pDFA_State: RE_pDFAState_t;
2899   pDFA_StateSub: RE_pDFAStateSub_t;
2900   Str: String;
2901 begin
2902   Strings.clear;
2903   Strings.BeginUpDate;
2904   for i := 0 to FStateList.Count-1 do begin
2905     pDFA_State := FStateList.items[i];
2906     if pDFA_State = FpInitialState then
2907       Str := Format('\8aJ\8en %2d : ', [i])
2908     else if pDFA_State^.Accepted then
2909       Str := Format('\8fI\97¹ %2d : ', [i])
2910     else
2911       Str := Format('\8fó\91Ô %2d : ', [i]);
2912     pDFA_StateSub := pDFA_State^.next;
2913     while pDFA_StateSub <> nil do begin
2914       if pDFA_StateSub^.CharClass.StartChar <> pDFA_StateSub^.CharClass.EndChar then
2915          Str := Str + Format('\95\8e\9a %s \82©\82ç \95\8e\9a%s \82Å \8fó\91Ô %2d \82Ö :',
2916           [DebugWCharToStr(pDFA_StateSub^.CharClass.StartChar),
2917            DebugWCharToStr(pDFA_StateSub^.CharClass.EndChar),
2918           FStateList.IndexOf(pDFA_StateSub^.TransitTo)])
2919
2920       else if pDFA_StateSub^.CharClass.StartChar = FNFA.LHeadWChar then begin
2921         Str := Str + Format('\95\93ª\83R\81[\83h %s \82Å \8fó\91Ô %2d \82Ö :',
2922           [DebugWCharToStr(pDFA_StateSub^.CharClass.StartChar),
2923           FStateList.IndexOf(pDFA_StateSub^.TransitTo)]);
2924       end else if pDFA_StateSub^.CharClass.StartChar = FNFA.LTailWChar then begin
2925         Str := Str + Format('\95\94ö\83R\81[\83h %s \82Å \8fó\91Ô %2d \82Ö :',
2926           [DebugWCharToStr(pDFA_StateSub^.CharClass.StartChar),
2927           FStateList.IndexOf(pDFA_StateSub^.TransitTo)]);
2928       end else
2929         Str := Str + Format('\95\8e\9a %s \82Å \8fó\91Ô %2d \82Ö :',
2930           [DebugWCharToStr(pDFA_StateSub^.CharClass.StartChar),
2931           FStateList.IndexOf(pDFA_StateSub^.TransitTo)]);
2932
2933       pDFA_StateSub := pDFA_StateSub^.Next;
2934     end;
2935     Strings.Add(Str);
2936   end;
2937   Strings.EndUpDate;
2938 end;
2939 {$ENDIF}
2940
2941 { -=================== TRegularExpression Class ==============================-}
2942 constructor TRegularExpression.Create(AOwner: TComponent);
2943 begin
2944   inherited Create(AOwner);
2945   FRegExpList := TStringList.Create;
2946   FRegExpListMax := 30; {RegExpList\82Ì\8d\80\96Ú\90\94\90Ý\92è 30}
2947   {FCurrentIndex = 0 \82Í\83k\83\8b\82Ì\90³\8bK\95\\8c»\82Å\8fí\82É\8eg\82¦\82é\82æ\82¤\82É\82·\82é\81B}
2948   FCurrentIndex := FRegExpList.Add('');
2949   FPreProcessor := TREPreProcessor.Create('');
2950   Translate(FRegExpList[FCurrentIndex]);
2951 end;
2952
2953 destructor TRegularExpression.Destroy;
2954 begin
2955   FPreProcessor.Free;
2956   DisposeRegExpList;
2957   inherited Destroy;
2958 end;
2959
2960 {\90³\8bK\95\\8c»\83\8a\83X\83g(FRegExpList: TStringList)\82ÆObjects\83v\83\8d\83p\83e\83B\82É\8c\8b\82Ñ\95t\82¯\82ç\82ê\82½
2961  TRE_DFA\83I\83u\83W\83F\83N\83g\82ð\94j\8aü}
2962 procedure TRegularExpression.DisposeRegExpList;
2963 var
2964   i: Integer;
2965 begin
2966   if FRegExpList <> nil then begin
2967     with FRegExpList do begin
2968       for i := 0 to Count-1 do begin
2969         TRE_DFA(Objects[i]).Free;
2970       end;
2971     end;
2972     FRegExpList.Free;
2973     FRegExpList := nil;
2974   end;
2975 end;
2976
2977 { ---------------------- \83v\83\8d\83p\83e\83\83A\83N\83Z\83\83\81\83\\83b\83h -----------------}
2978 {RegExp\83v\83\8d\83p\83e\83B\82Ìwrite\83\81\83\\83b\83h}
2979 procedure TRegularExpression.SetRegExp(Str: String);
2980 var
2981   OrigRegExp: String;
2982   function FindRegExpInList(RegExpStr: String): Integer;
2983   var
2984     i: Integer;
2985   begin
2986     result := -1;
2987     i := 0;
2988     while i < FRegExpList.Count do begin
2989       if RegExpStr = FRegExpList[i] then begin
2990         result := i;
2991         exit;
2992       end;
2993       Inc(i);
2994     end;
2995   end;
2996 begin
2997   OrigRegExp := Str;{\83v\83\8a\83v\83\8d\83Z\83b\83T\82ð\92Ê\82é\91O\82Ì\90³\8bK\95\\8c»\82ð\91Þ\94ð}
2998   with FPreProcessor do begin
2999     TargetRegExpStr := Str;
3000     Run;
3001     Str := ProcessedRegExpStr;
3002   end;
3003
3004   try
3005     FCurrentIndex := FindRegExpInList(Str);
3006     {FRegExpList\93à\82É\83L\83\83\83b\83V\83\85\82³\82ê\82Ä\82¢\82È\82¢\82Æ\82«\82Í\81A\83R\83\93\83p\83C\83\8b}
3007     if FCurrentIndex = -1 then begin
3008       if FRegExpList.Count = FRegExpListMax then begin
3009         TRE_DFA(FRegExpList.Objects[FRegExpList.Count-1]).Free;
3010         FRegExpList.Delete(FRegExpList.Count-1);
3011       end;
3012       FRegExpList.Insert(1, Str);
3013       FCurrentIndex := 1;
3014       Translate(FRegExpList[1]);
3015     end;
3016     FRegExp := OrigRegExp;
3017   except
3018     {\97á\8aO\82ª\94­\90\82µ\82½\82Æ\82«\82Í\81A\8fí\82É\83k\83\8b\90³\8bK\95\\8c»\82ð\90Ý\92è\82·\82é\81B}
3019     on Exception do begin
3020       FCurrentIndex := 0;
3021       FRegExp := '';
3022       raise;
3023     end;
3024   end;
3025 end;
3026
3027 {RegExp\83v\83\8d\83p\83e\83B\82Ìread\83\81\83\\83b\83h}
3028 function TRegularExpression.GetProcessedRegExp: String;
3029 begin
3030   result := FRegExpList[FCurrentIndex];
3031 end;
3032
3033 {ListOfFuzzyCharDic\83v\83\8d\83p\83e\83B read\83\81\83\\83b\83h}
3034 function TRegularExpression.GetListOfFuzzyCharDic: TList;
3035 begin
3036   result := FPreProcessor.ListOfFuzzyCharDic;
3037 end;
3038
3039 {GetListOfSynonymDic\83v\83\8d\83p\83e\83B read\83\81\83\\83b\83h}
3040 function TRegularExpression.GetListOfSynonymDic: TList;
3041 begin
3042   result := FPreProcessor.ListOfSynonymDic;
3043 end;
3044
3045 {RegExpIsSimple\83v\83\8d\83p\83e\83B read\83\81\83\\83b\83h}
3046 function TRegularExpression.GetRegExpIsSimple: Boolean;
3047 begin
3048   result := GetCurrentDFA.RegExpIsSimple;
3049 end;
3050
3051 {SimpleRegExp\83v\83\8d\83p\83e\83B read\83\81\83\\83b\83h}
3052 function TRegularExpression.GetSimpleRegExp: String;
3053 begin
3054   result := GetCurrentDFA.SimpleRegExpStr;
3055 end;
3056
3057 {HasLHead\83v\83\8d\83p\83e\83B read\83\81\83\\83b\83h}
3058 function TRegularExpression.GetHasLHead: Boolean;
3059 begin
3060   result := GetCurrentDFA.RegExpHasLHead;
3061 end;
3062
3063 {HasLTail\83v\83\8d\83p\83e\83B write\83\81\83\\83b\83h}
3064 function TRegularExpression.GetHasLTail: Boolean;
3065 begin
3066   result := GetCurrentDFA.RegExpHasLTail;
3067 end;
3068
3069 {\8c»\8dÝ\82Ì\90³\8bK\95\\8c»\82É\91Î\89\9e\82·\82éTRE_DFA\8c^\83I\83u\83W\83F\83N\83g\82ð\93¾\82é}
3070 function TRegularExpression.GetCurrentDFA: TRE_DFA;
3071 begin
3072   result := TRE_DFA(FRegExpList.Objects[FCurrentIndex]);
3073 end;
3074
3075 {DFA\8fó\91Ô\95\\82Ì\8f\89\8aú\8fó\91Ô\82ð\95\\82·\83m\81[\83h\82Ö\82Ì\83|\83C\83\93\83^\82ð\93¾\82é\82±\82Æ\82ª\82Å\82«\82é\81B}
3076 function TRegularExpression.GetpInitialDFAState: RE_pDFAState_t;
3077 begin
3078   result := TRE_DFA(FRegExpList.Objects[FCurrentIndex]).pInitialState;
3079 end;
3080
3081 function  TRegularExpression.GetUseFuzzyCharDic: Boolean;
3082 begin
3083   result := FPreProcessor.UseFuzzyCharDic;
3084 end;
3085
3086 procedure TRegularExpression.SetUseFuzzyCharDic(Val: Boolean);
3087 begin
3088   FPreProcessor.UseFuzzyCharDic := Val;
3089   Self.RegExp := FRegExp; {\90V\82µ\82¢\90Ý\92è\82Å\8dÄ\83R\83\93\83p\83C\83\8b}
3090 end;
3091
3092 function  TRegularExpression.GetUseSynonymDic: Boolean;
3093 begin
3094   result := FPreProcessor.UseSynonymDic;
3095 end;
3096
3097 procedure TRegularExpression.SetUseSynonymDic(Val: Boolean);
3098 begin
3099   FPreProcessor.UseSynonymDic := Val;
3100   Self.RegExp := FRegExp; {\90V\82µ\82¢\90Ý\92è\82Å\8dÄ\83R\83\93\83p\83C\83\8b}
3101 end;
3102
3103 function TRegularExpression.GetLineHeadWChar: WChar_t;
3104 begin
3105   result := CONST_LINEHEAD;
3106 end;
3107
3108 function TRegularExpression.GetLineTailWChar: WChar_t;
3109 begin
3110   result := CONST_LINETAIL;
3111 end;
3112
3113 {*****     \90³\8bK\95\\8c»\95\8e\9a\97ñ\81¨\8d\\95\96Ø\8d\\91¢\81¨NFA\81¨DFA \82Ì\95Ï\8a·\82ð\8ds\82¤ *****}
3114 procedure TRegularExpression.Translate(RegExpStr: String);
3115 var
3116   DFA: TRE_DFA;
3117   Parser: TREParser;
3118   NFA: TRE_NFA;
3119 begin
3120   DFA := nil;
3121   try
3122     Parser := TREParser.Create(RegExpStr);
3123     try
3124       Parser.Run;
3125       NFA := TRE_NFA.Create(Parser, GetLineHeadWChar, GetLineTailWChar);
3126       try
3127         Self.FLineHeadWChar := NFA.LHeadWChar;
3128         Self.FLineTailWChar := NFA.LTailWChar;
3129         NFA.Run;
3130         DFA := TRE_DFA.Create(NFA);
3131         FRegExpList.Objects[FCurrentIndex] := DFA;
3132         TRE_DFA(FRegExpList.Objects[FCurrentIndex]).Run;
3133       finally
3134         NFA.Free;
3135       end;
3136     finally
3137       Parser.Free;
3138     end;
3139   except
3140     On Exception do begin
3141       DFA.Free;
3142       FRegExpList.Delete(FCurrentIndex);
3143       FCurrentIndex := 0;
3144       raise;
3145     end;
3146   end;
3147 end;
3148
3149 {\8fó\91Ô DFAstate\82©\82ç\95\8e\9a\82\83\82É\82æ\82Á\82Ä\91J\88Ú\82µ\82Ä\81A\91J\88Ú\8cã\82Ì\8fó\91Ô\82ð\95Ô\82·\81B
3150  \95\8e\9a\82\83\82É\82æ\82Á\82Ä\91J\88Ú\8fo\97\88\82È\82¯\82ê\82Înil\82ð\95Ô\82·}
3151 function TRegularExpression.NextDFAState(DFAState: RE_pDFAState_t; c: WChar_t): RE_pDFAState_t;
3152 var
3153   pSub: RE_pDFAStateSub_t;
3154 begin
3155   {\82P\82Â\82ÌDFAState\82ª\8e\9d\82 pSub\82Ì\83\8a\83\93\83N\82Å\82Í\83L\83\83\83\89\83N\83^\83N\83\89\83X\82ª\8f¸\8f\87\82É\82È\82ç\82ñ\82Å\82¢\82é\82±\82Æ
3156   \82ð\91O\92ñ\82Æ\82µ\82Ä\82¢\82é\81B}
3157   result := nil;
3158   pSub := DFAState^.next;
3159   while pSub <> nil do begin
3160     if c < pSub^.CharClass.StartChar then
3161       exit
3162     else if c <= pSub^.CharClass.EndChar then begin
3163       result := pSub^.TransitTo;
3164       exit;
3165     end;
3166     pSub := pSub^.next;
3167   end;
3168 end;
3169
3170 constructor TMatchCORE.Create(AOwner: TComponent);
3171 begin
3172   inherited Create(AOwner);
3173   FLineSeparator := mcls_CRLF;
3174 end;
3175
3176 procedure TMatchCORE.MatchStd(pText: PChar; var pStart, pEnd: PChar);
3177 var
3178   pDFAState: RE_pDFAState_t;
3179   pp: PChar;
3180 begin
3181   pStart := nil;
3182   pEnd := nil;
3183
3184   {pText\82ª\83k\83\8b\95\8e\9a\97ñ\82Å\81A\90³\8bK\95\\8c»\82ª\83k\83\8b\95\8e\9a\97ñ\82É\88ê\92v\82·\82é\82Æ\82«}
3185   if (Byte(pText^) = CONST_NULL) and GetCurrentDFA.pInitialState.Accepted then begin
3186     pStart := pText;
3187     pEnd := pText;
3188     exit;
3189   end;
3190
3191   {\92\8d\96Ú\93_\82ð\82P\95\8e\9a\82Ã\82Â\82¸\82ç\82µ\82È\82ª\82ç\83}\83b\83`\82·\82é\8dÅ\8d\95\94\95ª\82ð\8c©\82Â\82¯\82é}
3192   while Byte(pText^) <> CONST_NULL do begin
3193     {DFA\82Ì\8f\89\8aú\8fó\91Ô\82ð\90Ý\92è}
3194     pDFAState := Self.GetCurrentDFA.pInitialState;
3195     pp := pText;
3196     {DFA\8fó\91Ô\95\\82É\95\8e\9a\82ð\93ü\97Í\82µ\82Ä\82¢\82Á\82Ä\83}\83b\83`\82·\82é\8dÅ\92·\95\94\95ª\82ð\8c©\82Â\82¯\82é}
3197     repeat
3198       if pDFAState^.accepted then begin
3199       {\8fI\97¹\8fó\91Ô\82Å\82 \82ê\82Î\8fê\8f\8a\82ð\8bL\98^\82µ\82Ä\82¨\82­\81B
3200        \8c\8b\89Ê\82Æ\82µ\82Ä\83}\83b\83`\82µ\82½\8dÅ\8d\8dÅ\92·\95\94\95ª\82ª\8bL\98^\82³\82ê\82é}
3201         pStart := pText;
3202         pEnd := pp;
3203       end;
3204       {\8e\9f\82Ì\8fó\91Ô\82É\91J\88Ú}
3205       pDFAState := NextDFAState(pDFAState, PCharGetWChar(pp));
3206     until pDFAState = nil;
3207
3208     {\83}\83b\83`\82µ\82½\82Æ\82«\82ÍExit}
3209     if pStart <> nil then
3210       exit;
3211
3212     {\92\8d\96Ú\88Ê\92u\82ð\82P\95\8e\9a\95ª\90i\82ß\82é\81B}
3213     if IsDBCSLeadByte(Byte(pText^)) then
3214       Inc(pText, 2)
3215     else
3216       Inc(pText);
3217   end;
3218   {\83}\83b\83`\82µ\82È\82¢\81B}
3219 end;
3220
3221 procedure TMatchCORE.MatchEX(pText: PChar; var pStart, pEnd: PChar);
3222 begin
3223   pStart := pText;
3224   pEnd := MatchHead(pText, GetCurrentDFA.pInitialState);
3225   if pEnd = nil then
3226     MatchEX_Inside(pText, pStart, pEnd);
3227 end;
3228
3229 procedure TMatchCORE.MatchEX_Inside(pText: PChar; var pStart, pEnd: PChar);
3230 var
3231   DFA: TRE_DFA;
3232   pInitialDFAState: RE_pDFAState_t;
3233 begin
3234   pStart := nil;
3235   pEnd := nil;
3236
3237   DFA := GetCurrentDFA;
3238   pInitialDFAState := DFA.pInitialState;
3239   while Byte(pText^) <> CONST_NULL do begin
3240     pEnd := MatchInSide(pText, pInitialDFAState);
3241     if pEnd <> nil then begin
3242       pStart := pText;
3243       exit;
3244     end else if (Byte(pText^) = CONST_LF) and
3245       DFA.RegExpHasLHead then begin
3246       pEnd := MatchHead(pText+1, pInitialDFAState);
3247       if pEnd <> nil then begin
3248         pStart := pText+1;
3249         exit;
3250       end;
3251     end;
3252     {\92\8d\96Ú\88Ê\92u\82ð\82P\95\8e\9a\95ª\90i\82ß\82é\81B}
3253     if IsDBCSLeadByte(Byte(pText^)) then
3254       Inc(pText, 2)
3255     else
3256       Inc(pText);
3257   end;
3258
3259   if DFA.RegExpHasLTail and (NextDFAState(pInitialDFAState, LineTailWChar) <> nil) then begin
3260   {\90³\8bK\95\\8c»\82ª\95\94ö\83\81\83^\83L\83\83\83\89\83N\83^\82Ì\82Ý\82Ì\82Æ\82«(RegExp = '$')\82Ì\93Á\8eê\8f\88\97\9d}
3261     pStart := pText;
3262     pEnd := pText;
3263   end;
3264  end;
3265
3266 function TMatchCORE.MatchHead(pText: PChar; pDFAState: RE_pDFAState_t): PChar;
3267 var
3268   pEnd: PChar;
3269 begin
3270 {\90³\8bK\95\\8c»\82ª\8ds\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82ñ\82Å\82¢\82é}
3271   if GetCurrentDFA.RegExpHasLHead then begin
3272     result := MatchInSide(pText, NextDFAState(pDFAState, LineHeadWChar));
3273     if result <> nil then begin
3274     {\83}\83b\83`\82µ\82½\81B\82±\82Ì\8e\9e\93_\82Å\81Aresult <> nil \8am\92è}
3275       pEnd := result;
3276       {\82³\82ç\82É\81ARegExp = '(^Love|Love me tender)'\82Å\81AText = 'Love me tender. Love me sweet'
3277        \82Ì\8fê\8d\87\82É\8dÅ\8d\8dÅ\92·\82Å\83}\83b\83`\82·\82é\82Ì\82Í\81A'Love me tender'\82Å\82È\82¯\82ê\82Î\82È\82ç\82È\82¢\82Ì\82Å\81A\82»\82Ì\88×\82Ì
3278        \83}\83b\83`\8c\9f\8d¸\82ð\8ds\82¤\81B}
3279       result := MatchInside(pText, pDFAState);
3280       if (result = nil) or (pEnd > result) then
3281         result := pEnd;
3282     end;
3283   end else begin
3284 {\90³\8bK\95\\8c»\82ª\8ds\93ª\83\81\83^\83L\83\83\83\89\83N\83^\82ð\8aÜ\82ñ\82Å\82¢\82È\82¢}
3285     result := MatchInside(pText, pDFAState);
3286   end;
3287 end;
3288
3289 function TMatchCORE.MatchInside(pText: PChar; pDFAState: RE_pDFAState_t): PChar;
3290 var
3291   pEnd: PChar;
3292   WChar: WChar_t;
3293   pPrevDFAState: RE_pDFAState_t;
3294 begin
3295   result := nil;
3296   pEnd := pText;
3297
3298   if pDFAState = nil then
3299     exit;
3300   repeat
3301     if pDFAState^.accepted then begin
3302     {\8fI\97¹\8fó\91Ô\82Å\82 \82ê\82Î\8fê\8f\8a\82ð\8bL\98^\82µ\82Ä\82¨\82­\81B
3303      \8c\8b\89Ê\82Æ\82µ\82Ä\83}\83b\83`\82µ\82½\8dÅ\8d\8dÅ\92·\95\94\95ª\82ª\8bL\98^\82³\82ê\82é}
3304         result :=  pEnd;
3305     end;
3306     pPrevDFAState := pDFAState;
3307     {DFA\82ð\8fó\91Ô\91J\88Ú\82³\82¹\82é}
3308     WChar := PCharGetWChar(pEnd);
3309     pDFAState := NextDFAState(pDFAState, WChar);
3310   until pDFAState = nil;
3311
3312   if (IsLineEnd(WChar) or (WChar = CONST_NULL)) and
3313     (NextDFAState(pPrevDFAState, LineTailWChar) <> nil) then begin
3314     {\8ds\96\96\83\81\83^\83L\83\83\83\89\83N\83^\82ð\93ü\97Í\82µ\82Ä\81Anil\88È\8aO\82ª\8bA\82Á\82Ä\82­\82é\82Æ\82«\82Í\95K\82¸\81A\83}\83b\83`\82·\82é}
3315       result := pEnd;
3316       if WChar <> CONST_NULL then
3317         Dec(result); {CR($0d)\82Ì\95ª Decrement}
3318   end;
3319 end;
3320
3321 function TMatchCORE.IsLineEnd(WChar: WChar_t): Boolean;
3322 begin
3323   result := False;
3324   case FLineSeparator of
3325     mcls_CRLF:  result := (WChar = CONST_CR);
3326     mcls_LF:    result := (WChar = CONST_LF);
3327   end;
3328 end;
3329
3330 { -========================== TAWKStr Class ==================================- }
3331 constructor TAWKStr.Create(AOwner: TComponent);
3332 begin
3333   inherited Create(AOwner);
3334   
3335   ListOfFuzzyCharDic.Add(RE_FuzzyCharDic); {\83L\83\83\83\89\83N\83^\93¯\88ê\8e\8b\8e«\8f\91\82ð\92Ç\89Á}
3336 end;
3337
3338 procedure TAWKStr.SetRegExp(Str: String);
3339 begin
3340   inherited SetRegExp(Str);
3341   if not (HasLHead or HasLTail) then begin
3342     FMatchProc := MatchStd;
3343   end else begin
3344     FMatchProc := MatchEx;
3345   end;
3346 end;
3347
3348 {\95\8e\9a\97ñ\92\86\82Ì'\' \82Å \88ø\97p\82³\82ê\82½\83L\83\83\83\89\83N\83^\82ð\8f\88\97\9d\82·\82é\81B \n, \t \\ ...}
3349 function TAWKStr.ProcessEscSeq(Text: String): String;
3350 var
3351   WChar: WChar_t;
3352   Index: Integer;
3353 begin
3354   result := '';
3355   Index := 1;
3356   while Index <= Length(Text) do begin
3357     WChar := GetWChar(Text, Index);
3358     if WChar = Ord('\') then
3359       result := result + WCharToStr(GetQuotedWChar(Text, Index))
3360     else
3361       result := result + WCharToStr(WChar);
3362   end;
3363 end;
3364
3365 {Sub, GSub\83\81\83\\83b\83h\82Å\8eg\97p\81B '&'\82ð\83}\83b\83`\82µ\82½\95\8e\9a\97ñ\82É\92u\8a·\82¦\82é}
3366 function TAWKStr.Substitute_MatchStr_For_ANDChar(Text: String; MatchStr: String): String;
3367 var
3368   i: Integer;
3369   aStr: String;
3370   WCh, WCh2: WChar_t;
3371 begin
3372   i := 1;
3373   aStr := '';
3374 {'\&'\82ð'\\&'\82É\82µ\82Ä\82©\82ç}
3375   while i <= Length(Text) do begin
3376     WCh := GetWChar(Text, i);
3377     if WCh = CONST_YEN then begin
3378       aStr := aStr + WCharToStr(WCh);
3379
3380       WCh := GetWChar(Text, i);
3381       if WCh = CONST_ANP then begin
3382         aStr := Concat(aStr, WCharToStr(CONST_YEN));
3383       end;
3384     end;
3385     aStr := aStr + WCharToStr(WCh);
3386   end;
3387
3388 {\83G\83X\83P\81[\83v\81E\83V\81[\83P\83\93\83X\82ð\8f\88\97\9d}
3389   Text := ProcessEscSeq(aStr);
3390
3391 {'&' \82ð MatchStr\82Å\92u\8a·\82¦\81A'\&'\82ð'&'\82É\92u\8a·\82¦}
3392   result := '';
3393   i := 1;
3394   while i <= Length(Text) do begin
3395     WCh := GetWChar(Text, i);
3396     if WCh = CONST_ANP then
3397       result := Concat(result, MatchStr)
3398     else if WCh = CONST_YEN then begin
3399       WCh2 := GetWChar(Text, i);
3400       if WCh2 = CONST_ANP then begin
3401         result := result + WCharToStr(WCh2);
3402       end else begin
3403         if WCh2 <> CONST_NULL then
3404           UnGetWChar(Text, i);
3405         result := result + WCharToStr(WCh);
3406       end;
3407     end else begin
3408       result := result + WCharToStr(WCh);
3409     end;
3410   end;
3411 end;
3412
3413 function TAWKStr.Match(Text: String; var RStart, RLength: Integer): Integer;
3414 var
3415   pStart, pEnd: PChar;
3416 begin
3417   FMatchProc(PChar(Text), pStart, pEnd);
3418   if pStart = nil then begin
3419     RStart := 0;
3420     RLength := 0;
3421     result := 0;
3422   end else begin
3423     RStart := pStart - PChar(Text)+1; {RStart\82Í\82P\83x\81[\83X}
3424     RLength := pEnd - pStart;
3425     result := RStart;
3426   end;
3427 end;
3428
3429 {AWK Like function Sub_Raw}
3430 function TAWKStr.Sub(SubText: String; var Text: String): Boolean;
3431 var
3432   pStart, pEnd: PChar;
3433   MatchStr: String;
3434 begin
3435   FMatchProc(PChar(Text), pStart, pEnd);
3436   if pStart <> nil then begin
3437 {\83}\83b\83`\82µ\82½}
3438     MatchStr := Copy(Text, pStart-PChar(Text)+1, pEnd-pStart); {\83}\83b\83`\82µ\82½\95\94\95ª}
3439     Delete(Text, pStart-PChar(Text)+1, pEnd-pStart);
3440     {SubText\82Ì\82È\82©\82Ì&\83L\83\83\83\89\83N\83^\82ð\83}\83b\83`\82µ\82½\95\94\95ª(MatchStr)\82Å\92u\8a·\82¦\82é\81B}
3441     SubText := Substitute_MatchStr_For_ANDChar(SubText, MatchStr);
3442     Insert(SubText, Text, pStart-PChar(Text)+1);
3443     result := True;
3444   end else begin
3445 {\83}\83b\83`\82µ\82È\82¢}
3446     result := False;
3447   end;
3448 end;
3449
3450 {AWK Like GSubRaw }
3451 function TAWKStr.GSub(SubText: String; var Text: String): Integer;
3452 var
3453   pStart, pEnd: PChar;
3454   ResultText, aText: String;
3455   MatchStr: String;
3456   WChar: WChar_t;
3457 begin
3458   ResultText := ''; {\8c\8b\89Ê\82Ì\95\8e\9a\97ñ\82ð\93ü\82ê\82é\95Ï\90\94}
3459   aText := Text;    {\8c\9f\8dõ\91Î\8fÛ\82Æ\82µ\82Ä\8eg\82¤}
3460   result := 0;
3461   FMatchProc(PChar(aText), pStart, pEnd);
3462   if pStart = nil then
3463     exit  {\89½\82à\83}\83b\83`\82µ\82È\82¢}
3464   else if aText = '' then begin
3465     result := 1; {\83}\83b\83`\82µ\82½\82ª Text=''}
3466     Text := Substitute_MatchStr_For_ANDChar(SubText, '');
3467     exit;
3468   end;
3469
3470   {\83}\83b\83`\82µ\82Ä Text <> ''}
3471   while True do begin
3472     ResultText := Concat(ResultText, Copy(aText, 1, pStart-PChar(aText)));{\91O\94¼\95\94\95ª}
3473     MatchStr := Copy(aText, pStart-PChar(aText)+1, pEnd-pStart);   {\83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ}
3474     MatchStr := Substitute_MatchStr_For_ANDChar(SubText, MatchStr);
3475     ResultText := Concat(ResultText, MatchStr);{+ \92u\8a·\95\8e\9a\97ñ}
3476
3477     if pStart = pEnd then begin {\8bó\95\8e\9a\97ñ\82É\83}\83b\83`\82µ\82½\82Æ\82«\82Ì\93Á\8eê\8f\88\97\9d}
3478       if isDBCSLeadByte(Byte(pStart^)) or
3479          ((LineSeparator = mcls_CRLF) and (Byte(pStart^) = CONST_CR)) then begin
3480         ResultText := Concat(ResultText, Copy(aText, pStart-PChar(aText)+1, 2));
3481         Inc(pEnd, 2);
3482       end else begin
3483         ResultText := Concat(ResultText, Copy(aText, pStart-PChar(aText)+1, 1));
3484         if Byte(pEnd^) <> CONST_NULL then
3485           Inc(pEnd, 1);
3486       end;
3487     end;
3488     Inc(result);
3489
3490     WChar := Byte((pEnd-1)^);
3491     {Chr($0a)\82ð\92²\82×\82é\88×\82¾\82¯\82È\82Ì\82Å\81A\82Q\83o\83C\83g\95\8e\9a\82Ì\8dl\97\95s\97v\81B aText = ''\82Í\82 \82è\82¦\82È\82¢}
3492     aText := String(pEnd);
3493     {\83}\83b\83`\82µ\82½\95\94\95ª\95\8e\9a\97ñ\82Ì\8cã\82Ì\95\94\95ª\82ðaText\82É\90Ý\92è}
3494     if aText = '' then
3495       break;
3496     if WChar = CONST_LF then begin
3497       FMatchProc(PChar(aText), pStart, pEnd);
3498       if pStart = nil then
3499         break;
3500     end else begin
3501       MatchEX_Inside(PChar(aText), pStart, pEnd);
3502       if pStart = nil then
3503         break;
3504     end;
3505   end;
3506   Text := Concat(ResultText, aText);
3507 end;
3508
3509 function TAWKStr.Split(Text: String; StrList: TStrings): Integer;
3510 var
3511   pStart, pEnd: PChar;
3512   Str: String;
3513 begin
3514   StrList.Clear;{\8c\8b\89Ê\95\8e\9a\97ñ\83\8a\83X\83g\82Ì\93à\97e\83N\83\8a\83A}
3515   Str := '';
3516   while Text <> '' do begin
3517     FMatchProc(PChar(Text), pStart, pEnd);
3518     if pStart = nil then begin
3519     {\83}\83b\83`\82µ\82È\82©\82Á\82½\82Æ\82«}
3520       StrList.Add(Concat(Str, Text));
3521       Str := '';
3522       break;
3523     end else if (pStart = PChar(Text)) and (pStart = pEnd) then begin
3524     {\90æ\93ª\82Ì\83k\83\8b\95\8e\9a\97ñ\82É\83}\83b\83`\82µ\82½\82Æ\82«\82Ì\93Á\8eê\8f\88\97\9d}
3525       if IsDBCSLeadByte(Byte(Text[1])) then begin
3526         Str := Concat(Str, Copy(Text, 1, 2));
3527         Text := Copy(Text, 3, Length(Text));
3528       end else begin
3529         Str := Concat(Str, Text[1]);
3530         Text := Copy(Text, 2, Length(Text));
3531       end;
3532     end else begin;
3533     {\83}\83b\83`\82µ\82½}
3534       StrList.Add(Concat(Str, Copy(Text, 1, pStart-PChar(Text))));
3535       Str := '';
3536       Text := String(pEnd);
3537       if Text = '' then begin
3538       {\8dÅ\8cã\94ö\82É\83}\83b\83`\82µ\82½\82Æ\82«\82Ì\93Á\8eê\8f\88\97\9d}
3539         StrList.Add('');
3540         break;
3541       end;
3542     end;
3543   end;
3544   if Str <> '' then
3545     StrList.Add(Str);
3546   result := StrList.Count;
3547 end;
3548
3549 { -=========================== TTxtFile Class ================================-}
3550 constructor TTxtFile.Create(aFileName: String; var CancelRequest: Boolean);
3551 begin
3552   inherited Create;
3553   FpCancelRequest := @CancelRequest; {CancelRequest\82ªTrue\82Å\93r\92\86\8fI\97¹\82·\82é}
3554
3555   FBuffSize := 1024*100; {\83o\83b\83t\83@\82Ì\83T\83C\83Y}
3556   FTailMargin := 100;
3557
3558   FFileName := aFileName;
3559   System.FileMode := 0; {\83t\83@\83C\83\8b\83A\83N\83Z\83X\83\82\81[\83\82ð\93Ç\82Ý\8fo\82µ\90ê\97p\82É\90Ý\92è}
3560   AssignFile(FF, FFileName);
3561   try
3562     Reset(FF, 1);
3563   except
3564     on E: EInOutError do begin
3565       raise EFileNotFound.Create(E.Message);
3566     end;
3567   end;
3568   FFileOpened := True;  { \83t\83@\83C\83\8b\83I\81[\83v\83\93\82Ì\83t\83\89\83O\81BDestroy\82Å\8eg\97p\82·\82é}
3569   FpBuff := AllocMem(FBuffSize+FTailMargin);
3570   FpBuff^ := Chr($0a);  { \83t\83@\83C\83\8b\90æ\93ª\8ds\82Ì\8ds\93ª\82É\82k\82e Chr($0a)\82ð\95t\89Á}
3571   BuffRead(FpBuff+1);
3572   Inc(FReadCount);      { \90æ\93ª\82Ì\82k\82e($0a)\82Ì\82Ô\82ñ\82ð\89Á\8eZ}
3573   FpBase := FpBuff;
3574   FpLineBegin := FpBuff;
3575   FpForward := FpBuff;
3576   FLineNo := 0;
3577 end;
3578
3579 destructor TTxtFile.Destroy;
3580 begin
3581   if FFileOpened then
3582     CloseFile(FF);
3583
3584   if FpBuff <> nil then begin
3585     FreeMem(FpBuff, FBuffSize+FTailMargin);
3586   end;
3587
3588   inherited Destroy;
3589 end;
3590
3591 procedure TTxtFile.BuffRead(pBuff: PChar);
3592 begin
3593   BlockRead(FF, pBuff^, FBuffSize, FReadCount);
3594   if FReadCount = 0 then begin
3595     {FpLineBegin := FpBase;}
3596     raise EEndOfFile.Create('End Of File');
3597   end;
3598
3599   {\93Ç\82Ý\8d\9e\82ñ\82¾\83f\81[\83^\82Ì\8dÅ\8cã\82É\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82ð\8f\91\82«\8d\9e\82Þ}
3600   if not Eof(FF) then begin
3601     (pBuff+FReadCount)^ := Chr(0);
3602   end else begin
3603     if (pBuff+FReadCount-1)^ <> Chr($0a) then begin
3604       (pBuff+FReadCount)^ := Chr($0a);
3605       (pBuff+FREadCount+1)^ := Chr(0);
3606       (pBuff+FReadCount+2)^ := Chr(0);
3607       Inc(FReadCount);
3608     end else begin
3609       (pBuff+FReadCount)^ := Chr(0);
3610       (pBuff+FreadCount+1)^ := Char(0);
3611     end;
3612   end;
3613
3614   Application.ProcessMessages;
3615   if FpCancelRequest^ then
3616     raise EGrepCancel.Create('CancelRequest');
3617 end;
3618
3619 procedure TTxtFile.IncPBaseNullChar(Ch: Char);
3620 var
3621   Distance: Integer;
3622 begin
3623   if FpBase = (PChar(FBrokenLine)+Length(FBrokenLine)) then begin
3624   {FBrokenLine(String\8c^) \82Ì\92\86\82ÅChr(0)\82É\92B\82µ\82½\82Æ\82«\81B}
3625     FpBase := FpBuff;
3626   end else begin    
3627   {FpBuff(PChar) \83o\83b\83t\83@\82Ì\92\86\82ÅChr(0)\82É\92B\82µ\82½\82Æ\82«\81B}    
3628     if FpBase < FpBuff+FReadCount then begin
3629     {\83t\83@\83C\83\8b\92\86\82Ì\95s\90³\82È\83k\83\8b\83L\83\83\83\89\83N\83^ Chr(0)\82Í\81ASpace($20)\82É\95â\90³}   
3630       FpBase^ := Chr($20);    
3631     end else begin    
3632     {\83o\83b\83t\83@\82Ì\8fI\82í\82è\82É\97\88\82½}    
3633       if Eof(FF) then begin   
3634       {\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\97\88\82½}    
3635         if Ch = Chr(0) then   
3636           Dec(FpBase);    
3637         raise EEndOfFile.Create('End Of File');   
3638       end else begin    
3639       {\83t\83@\83C\83\8b\82ð\82Ü\82¾\93Ç\82ß\82é}    
3640         if (FpLineBegin >= PChar(FBrokenLine)) and    
3641         (FpLineBegin < (PChar(FBrokenLine)+Length(FBrokenLine))) then begin
3642         {FpLineBegin\82ªFBrokenLine\82Ì\92\86\82ð\8ew\82µ\82Ä\82¢\82é\81B}    
3643           Distance := FpLineBegin-PChar(FBrokenLine);   
3644           FBrokenLine := Concat(FBrokenLine, String(FpBuff));   
3645           FpLineBegin := PChar(FBrokenLine)+Distance;   
3646           BuffRead(FpBuff);   
3647           FpBase := FpBuff;   
3648         end else begin    
3649         {FpLineBegin\82ª\83o\83b\83t\83@\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Ì\82Å\82»\82±\82©\82çFBrokenLine\82ð\8eæ\82é}    
3650           FBrokenLine := String(FpLineBegin);   
3651           BuffRead(FpBuff);   
3652           FpBase := FpBuff;   
3653           FpLineBegin := PChar(FBrokenLine);    
3654         end;
3655       end;    
3656     end;    
3657   end;    
3658 end;
3659
3660 {\8b@\94\\81F FpBase\82ð\83C\83\93\83N\83\8a\83\81\83\93\83g\82µ\82Ä\81A\8e\9f\82Ì\82P\83o\83C\83g\82ð\8ew\82·\82æ\82¤\82É\82·\82é\81B}
3661 function TTxtFile.IncPBase: Char;
3662 var
3663   ApBase: PChar;
3664 begin
3665   result := FpBase^;
3666   Inc(FpBase);
3667   if FpBase^ = Chr(0) then
3668   {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3669     IncPBaseNullChar(result);
3670   if result = Chr($0a) then begin
3671   {\89ü\8ds\8f\88\97\9d}
3672     if (FpBase < PChar(FBrokenLine)) or (FpBase > (PChar(FBrokenLine) +
3673     Length(FBrokenLine))) then begin
3674     {FpBase\82ª\83o\83b\83t\83@\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3675       FBrokenLine := '';
3676       FpLineBegin := FpBase;
3677       Inc(FLineNo);
3678     end else begin
3679     {FpBase\82ªFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3680       FpLineBegin := FpBase;
3681       Inc(FLineNo);
3682     end;
3683   end;
3684   if FpBase^ = Chr($0d) then begin
3685     ApBase := FpBase;
3686     Inc(FpBase);
3687     if FpBase^ = Chr(0) then
3688     {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3689       IncPBaseNullChar(result);
3690     if FpBase^ <> Chr($0a) then begin
3691     { CR($0d)\82Ì\8e\9f\82ªLF($0a)\82Å\82È\82¢\82Æ\82«\82Í\81A$0d\82ð$0a\82É\92u\8a·\82·\82é\81B}
3692       if FpBase = FpBuff then
3693         FpBase := PChar(FBrokenLine)+Length(FBrokenLine)-1
3694       else
3695         FpBase := ApBase;
3696       FpBase^ := Chr($0a);
3697     end
3698   end;
3699   FpForward := FpBase;
3700 end;
3701
3702 function TTxtFile.AdvanceBase: WChar_t;
3703 var
3704   ApBase: PChar;
3705   Ch: Char;
3706 begin
3707   {\81«\8d\82\91¬\89»\82Ì\82½\82ßIncPBase\96\84\82ß\8d\9e\82Ý}
3708     Ch := FpBase^;
3709     Inc(FpBase);
3710     if FpBase^ = Chr(0) then
3711     {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3712       IncPBaseNullChar(Ch);
3713     if Ch = Chr($0a) then begin
3714     {\89ü\8ds\8f\88\97\9d}
3715       if (FpBase < PChar(FBrokenLine)) or (FpBase > (PChar(FBrokenLine) +
3716       Length(FBrokenLine))) then begin
3717       {FpBase\82ª\83o\83b\83t\83@\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3718         FBrokenLine := '';
3719         FpLineBegin := FpBase;
3720         Inc(FLineNo);
3721       end else begin
3722       {FpBase\82ªFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3723         FpLineBegin := FpBase;
3724         Inc(FLineNo);
3725       end;
3726     end;
3727     if FpBase^ = Chr($0d) then begin
3728       ApBase := FpBase;
3729       Inc(FpBase);
3730       if FpBase^ = Chr(0) then
3731       {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3732         IncPBaseNullChar(ApBase^);
3733       if FpBase^ <> Chr($0a) then begin
3734       { CR($0d)\82Ì\8e\9f\82ªLF($0a)\82Å\82È\82¢\82Æ\82«\82Í\81A$0d\82ð$0a\82É\92u\8a·\82·\82é\81B}
3735         if FpBase = FpBuff then
3736           FpBase := PChar(FBrokenLine)+Length(FBrokenLine)-1
3737         else
3738           FpBase := ApBase;
3739         FpBase^ := Chr($0a);
3740       end
3741     end;
3742     {\81ª\8d\82\91¬\89»\82Ì\82½\82ßIncPBase\96\84\82ß\8d\9e\82Ý}
3743     result := Byte(Ch);
3744     case result of
3745       $81..$9F, $E0..$FC: begin
3746           {\81«\8d\82\91¬\89»\82Ì\82½\82ßIncPBase\96\84\82ß\8d\9e\82Ý}
3747           Ch := FpBase^;
3748           Inc(FpBase);
3749           if FpBase^ = Chr(0) then
3750           {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3751             IncPBaseNullChar(Ch);
3752           if Ch = Chr($0a) then begin
3753           {\89ü\8ds\8f\88\97\9d}
3754             if (FpBase < PChar(FBrokenLine)) or (FpBase > (PChar(FBrokenLine) +
3755             Length(FBrokenLine))) then begin
3756             {FpBase\82ª\83o\83b\83t\83@\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3757               FBrokenLine := '';
3758               FpLineBegin := FpBase;
3759               Inc(FLineNo);
3760             end else begin
3761             {FpBase\82ªFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3762               FpLineBegin := FpBase;
3763               Inc(FLineNo);
3764             end;
3765           end;
3766           if FpBase^ = Chr($0d) then begin
3767             ApBase := FpBase;
3768             Inc(FpBase);
3769             if FpBase^ = Chr(0) then
3770             {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3771               IncPBaseNullChar(ApBase^);
3772             if FpBase^ <> Chr($0a) then begin
3773             { CR($0d)\82Ì\8e\9f\82ªLF($0a)\82Å\82È\82¢\82Æ\82«\82Í\81A$0d\82ð$0a\82É\92u\8a·\82·\82é\81B}
3774               if FpBase = FpBuff then
3775                 FpBase := PChar(FBrokenLine)+Length(FBrokenLine)-1
3776               else
3777                 FpBase := ApBase;
3778               FpBase^ := Chr($0a);
3779             end
3780           end;
3781           {\81ª\8d\82\91¬\89»\82Ì\82½\82ßIncPBase\96\84\82ß\8d\9e\82Ý}
3782           result := (result shl 8) or Byte(Ch);
3783         end;
3784     end;
3785     FpForward := FpBase;
3786 end;
3787
3788 procedure TTxtFile.GetCharNullChar(Ch: Char);
3789 var
3790   Distance, Distance2: Integer;
3791 begin
3792   if FpForward = (PChar(FBrokenLine)+Length(FBrokenLine)) then begin
3793   {FBrokenLine(String\8c^) \82Ì\92\86\82ÅChr(0)\82É\92B\82µ\82½\82Æ\82«\81B}
3794     FpForward := FpBuff;
3795   end else begin
3796   {FpBuff \83o\83b\83t\83@\82Ì\92\86\82ÅChr(0)\82É\92B\82µ\82½\82Æ\82«\81B}
3797     if FpForward < FpBuff+FReadCount then begin
3798     {\83t\83@\83C\83\8b\92\86\82Ì\95s\90³\82È\83k\83\8b\83L\83\83\83\89\83N\83^ Chr(0) \82Í Space($20)\82É\82·\82é\81B}
3799       FpForward^ := Chr($20);
3800     end else begin
3801     {\83o\83b\83t\83@\82Ì\8fI\82í\82è\82É\97\88\82½}
3802       if Eof(FF) then begin
3803       {\82·\82Å\82É\83t\83@\83C\83\8b\82Ì\8fI\82í\82è\82É\92B\82µ\82Ä\82¢\82é\82Æ\82«}
3804         if Ch = Chr(0) then
3805           Dec(FpForward);     {\82¸n\82Á\82Æresut = Chr(0)\82ð\95Ô\82·\82æ\82¤\82É\82·\82é}
3806         exit;
3807       end else begin
3808       {\82Ü\82¾\83t\83@\83C\83\8b\82ð\93Ç\82ß\82é\82Æ\82«}
3809         if (FpLineBegin >= PChar(FBrokenLine)) and
3810         (FpLineBegin < PChar(FBrokenLine)+Length(FBrokenLine)) then begin
3811         {FpLineBegin\82ªFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3812           Distance := FpLineBegin-PChar(FBrokenLine);
3813           if (FpBase >= PChar(FBrokenLine)) and
3814           (FpBase < PChar(FBrokenLine)+Length(FBrokenLine)) then
3815           {FpBase\82àFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3816             Distance2 := FpBase-PChar(FBrokenLine)
3817           else
3818           {FpBase\82Í\83o\83b\83t\83@\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3819             Distance2 := Length(FBrokenLine)+FpBase-FpBuff;
3820           FBrokenLine := Concat(FBrokenLine, String(FpBuff));
3821           FpLineBegin := PChar(FBrokenLine)+Distance;
3822           FpBase := PChar(FBrokenLine)+Distance2;
3823           BuffRead(FpBuff);
3824           FpForward := FpBuff;
3825         end else begin
3826         {FpLineBegin\82ª\83o\83b\83t\83@\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3827           FBrokenLine := String(FpLineBegin);
3828           FpBase := PChar(FBrokenLine)+(FpBase-FpLineBegin);
3829           FpLineBegin := PChar(FBrokenLine);
3830           BuffRead(FpBuff);
3831           FpForward := FpBuff;
3832         end;
3833       end;
3834     end;
3835   end;
3836 end;
3837
3838 function TTxtFile.GetChar: Char;
3839 var
3840   ApForward: PChar;
3841 begin
3842   ApForward := FpForward;
3843   result := FpForward^;
3844   Inc(FpForward);
3845   {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3846   if FpForward^ = Chr(0) then
3847     GetCharNullChar(result);
3848
3849   if result = Chr($0d) then begin
3850     if FpForward^ <> Chr($0a) then begin
3851     {CR($0d)\82Ì\8e\9f\82ªLF($0a)\82Å\82È\82¢\82Æ\82«\82Í\81A$0d\82ð$0a\82É\92u\8a·\82·\82é\81B}
3852       if FpForward = FpBuff then
3853         FpForward := PChar(FBrokenLine)+Length(FBrokenLine)-1
3854       else
3855         FpForward := ApForward;
3856       FpForward^ := Chr($0a);
3857       result := Chr($0a);
3858     end else begin
3859       result := FpForward^;
3860       Inc(FpForward);
3861       {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3862       if FpForward^ = Chr(0) then
3863         GetCharNullChar(result);
3864     end;
3865   end;
3866 end;
3867
3868 function TTxtFile.GetWChar: WChar_t;
3869 var
3870   ApForward: PChar;
3871   Ch: Char;
3872 begin
3873   ApForward := FpForward;
3874   Ch := FpForward^;
3875   Inc(FpForward);
3876   {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3877   if FpForward^ = Chr(0) then
3878     GetCharNullChar(Ch);
3879
3880   if Ch = Chr($0d) then begin
3881     if FpForward^ <> Chr($0a) then begin
3882     {CR($0d)\82Ì\8e\9f\82ªLF($0a)\82Å\82È\82¢\82Æ\82«\82Í\81A$0d\82ð$0a\82É\92u\8a·\82·\82é\81B}
3883       if FpForward = FpBuff then
3884         FpForward := PChar(FBrokenLine)+Length(FBrokenLine)-1
3885       else
3886         FpForward := ApForward;
3887       FpForward^ := Chr($0a);
3888       Ch := Chr($0a);
3889     end else begin
3890       Ch := FpForward^;
3891       Inc(FpForward);
3892       {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3893       if FpForward^ = Chr(0) then
3894         GetCharNullChar(Ch);
3895     end;
3896   end;
3897   result := Byte(Ch);
3898   case result of
3899     $81..$9F, $E0..$FC: begin
3900         Ch := FpForward^;
3901         Inc(FpForward);
3902         {\83k\83\8b\81E\83L\83\83\83\89\83N\83^\82Ì\8f\88\97\9d}
3903         if FpForward^ = Chr(0) then
3904           GetCharNullChar(Ch);
3905         result := (result shl 8) or Byte(Ch);
3906       end;
3907   end;
3908 end;
3909
3910 function TTxtFile.GetThisLine: RE_LineInfo_t;
3911 var
3912   i: Integer;
3913 begin
3914   Application.ProcessMessages;
3915   if FpCancelRequest^ then
3916     raise EGrepCancel.Create('CancelRequest');
3917
3918     {\8ds\96\96\82ð\8c©\82Â\82¯\82é\81B}
3919     while FpBase^ <> Chr($0a) do begin
3920       IncPBase;
3921     end;
3922
3923   if (FpLineBegin >= PChar(FBrokenLine)) and
3924   (FpLineBegin < PChar(FBrokenLine)+Length(FBrokenLine)) then begin
3925   {FpLineBegin\82ªFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3926     if (FpBase >= PChar(FBrokenLine)) and
3927     (FpBase < PChar(FBrokenLine)+Length(FBrokenLine)) then begin
3928     {FpBase\82àFBrokenLine\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3929       result.Line := Copy(FBrokenLine, FpLineBegin-PChar(FBrokenLine)+1,
3930                         FpBase-FpLineBegin);
3931     end else begin
3932     {FpBase\82Í\83o\83b\83t\83@\92\86\82ð\8ew\82µ\82Ä\82¢\82é\82Æ\82«}
3933       SetString(result.Line, FpBuff, FpBase-FpBuff);
3934       result.Line := Concat(Copy(FBrokenLine, FpLineBegin-PChar(FBrokenLine)+1,
3935                             Length(FBrokenLine)), result.Line);
3936     end;
3937   end else begin
3938     SetString(result.Line, FpLineBegin, FpBase-FpLineBegin);
3939   end;
3940
3941   {TrimRight}
3942   i := Length(result.Line);
3943   while (i > 0) and (result.Line[i] in [Chr($0d), Chr($0a)]) do Dec(I);
3944   result.Line := Copy(result.Line, 1, i);
3945
3946   result.LineNo := FLineNo;
3947 end;
3948
3949 function StringToWordArray(Str: String; pWCharArray: PWordArray): Integer;
3950 var
3951   i, j: Integer;
3952   WChar: WChar_t;
3953 begin
3954   i := 1;
3955   j := 0;
3956   WChar := GetWChar(Str, i);
3957   while WChar <> 0 do begin
3958     pWCharArray^[j] := WChar;
3959     Inc(j);
3960     WChar := GetWChar(Str, i);
3961   end;
3962   pWCharArray^[j] := 0;
3963   result := j;
3964 end;
3965
3966 constructor TGrep.Create(AOwner: TComponent);
3967 begin
3968   inherited Create(AOwner);
3969
3970   ListOfFuzzyCharDic.Add(RE_FuzzyCharDic); {\83L\83\83\83\89\83N\83^\93¯\88ê\8e\8b\8e«\8f\91\82ð\92Ç\89Á}
3971 end;
3972
3973 procedure TGrep.SetRegExp(Str: String);
3974 begin
3975   inherited SetRegExp(Str);
3976   if Self.RegExpIsSimple then
3977     FGrepProc := GrepByStr
3978   else
3979     FGrepProc := GrepByRegExp;
3980 end;
3981
3982 function TGrep.GetLineHeadWChar: WChar_t;
3983 begin
3984   result := CONST_LF;
3985 end;
3986
3987 function TGrep.GetLineTailWChar: WChar_t;
3988 begin
3989   result := CONST_LF;
3990 end;
3991
3992 procedure TGrep.GrepByRegExp(FileName: String);
3993 var
3994   TxtFile: TTxtFile;
3995   pDFAState,pInitialDFAState: RE_pDFAState_t;
3996   LineInfo: RE_LineInfo_t;
3997   DFA: TRE_DFA;
3998   WChar: WChar_t;
3999   pSub: RE_pDFAStateSub_t;
4000 begin
4001   {OnMatch\83C\83x\83\93\83g\83n\83\93\83h\83\89\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82È\82¢\82Æ\82«\82Í\81A\89½\82à\82µ\82È\82¢}
4002   if not Assigned(FOnMatch) then
4003     exit;
4004
4005   FCancel := False;
4006   DFA := GetCurrentDFA;
4007   pInitialDFAState := DFA.pInitialState;
4008   try
4009     TxtFile := TTxtFile.Create(FileName, Self.FCancel);
4010   except on EEndOfFile do exit; {\83t\83@\83C\83\8b\83T\83C\83Y\82O\82Ì\82Æ\82«\82Íexit} end;
4011
4012   try
4013     try
4014       {\8c\9f\8dõ}
4015       while True do begin
4016         repeat
4017           WChar := TxtFile.AdvanceBase;
4018           {\81«NextDFAState\83\81\83\\83b\83h\96\84\82ß\8d\9e\82Ý}
4019           pDFAState := nil;
4020           pSub := pInitialDFAState^.next;
4021           while pSub <> nil do begin
4022             if WChar < pSub^.CharClass.StartChar then
4023               break
4024             else if WChar <= pSub^.CharClass.EndChar then begin
4025               pDFAState := pSub^.TransitTo;
4026               break;
4027             end;
4028             pSub := pSub^.next;
4029           end;
4030           {\81ªNextDFAState\83\81\83\\83b\83h\96\84\82ß\8d\9e\82Ý}
4031         until pDFAState <> nil;
4032
4033         while True do begin
4034           if pDFAState^.accepted then begin
4035           {\83}\83b\83`\82µ\82½}
4036             LineInfo := TxtFile.GetThisLine;
4037             FOnMatch(Self, LineInfo);
4038             break;
4039           end;
4040
4041           {DFA\82ð\8fó\91Ô\91J\88Ú\82³\82¹\82é}
4042           pDFAState := NextDFAState(pDFAState, TxtFile.GetWChar);
4043           if pDFAState = nil then begin
4044             break;
4045           end;
4046         end;
4047       end;
4048     finally TxtFile.Free; end;
4049   except on EEndOfFile do ; end; {Catch EEndOfFile}
4050 end;
4051
4052 procedure TGrep.GrepByStr(FileName: String);
4053 var
4054   TxtFile: TTxtFile;
4055   Pattern: String;
4056   pPat: PWordArray;
4057   PatLen: Integer;
4058   i: Integer;
4059   LineInfo: RE_LineInfo_t;
4060 begin
4061   FCancel := False;
4062   Pattern := Self.SimpleRegExp;
4063   {OnMatch\83C\83x\83\93\83g\83n\83\93\83h\83\89\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82È\82¢\82Æ\82«\82Í\81A\89½\82à\82µ\82È\82¢}
4064   if not Assigned(FOnMatch) then
4065     exit;
4066
4067   try
4068     TxtFile := TTxtFile.Create(FileName, Self.FCancel);
4069   except on EEndOfFile do exit; {\83t\83@\83C\83\8b\83T\83C\83Y\82O\82Ì\82Æ\82«\82Íexit}  end;
4070
4071   try
4072     pPat := AllocMem(Length(Pattern)*2+2);
4073   try
4074     PatLen := StringToWordArray(Pattern, pPat);
4075     try
4076       while True do begin
4077         while (TxtFile.AdvanceBase <> Word(pPat^[0])) do
4078           ;
4079         i := 1;
4080         while True do begin
4081           if i = PatLen then begin
4082             LineInfo := TxtFile.GetThisLine;
4083             FOnMatch(Self, LineInfo);
4084             break;
4085           end;
4086           if TxtFile.GetWChar = Word(pPat^[i]) then
4087             Inc(i)
4088           else
4089             break;
4090         end;
4091       end;
4092     except on EEndOfFile do ;{Catch EEndOfFile} end;
4093   finally FreeMem(pPat, Length(Pattern)*2+2); end;
4094   finally TxtFile.Free; end;
4095 end;
4096
4097 procedure MakeFuzzyCharDic;
4098 var
4099   StrList: TStrings;
4100   i: Integer;
4101 begin
4102   RE_FuzzyCharDic := nil;
4103   RE_FuzzyCharDic := TList.Create;
4104
4105   i := 0;
4106   repeat
4107     StrList := TStringList.Create;
4108     try
4109       RE_FuzzyCharDic.Add(StrList);
4110     except
4111       on Exception do begin
4112         StrList.Free;
4113         raise;
4114       end;
4115     end;
4116
4117     StrList.CommaText := REFuzzyWChars[i];
4118     Inc(i);
4119   until i > High(REFuzzyWChars);
4120 end;
4121
4122 procedure DestroyFuzzyCharDic;
4123 var
4124   i: Integer;
4125 begin
4126   for i := 0 to RE_FuzzyCharDic.Count-1 do
4127     TStringList(RE_FuzzyCharDic[i]).Free;
4128   RE_FuzzyCharDic.Free;
4129 end;
4130
4131 procedure Register;
4132 begin
4133   RegisterComponents('RegExp', [TGrep, TAWKStr]);
4134 end;
4135
4136 initialization
4137   MakeFuzzyCharDic;
4138
4139 finalization
4140   DestroyFuzzyCharDic;
4141
4142 end.