1 using System;
  2 using System.Lex;
  3 using RexTokens;
  4 
  5 namespace System.RegularExpressions
  6 {
  7     public Nfa ParseRegularExpressionPattern(RexLexer& lexerContext& context)
  8     {
  9         lexer.SetFlag(LexerFlags.farthestError);
 10         ++lexer;
 11         Nfa nfa;
 12         bool matched = ParseAlternative(lexercontextnfa);
 13         if (!matched || *lexer != END)
 14         {
 15             lexer.ThrowFarthestError();
 16         }
 17         return nfa;
 18     }
 19     
 20     public bool ParseAlternative(RexLexer& lexerContext& contextNfa& nfa)
 21     {
 22         long save = lexer.GetPos();
 23         if (ParseCatenation(lexercontextnfa))
 24         {
 25             while (*lexer == ALT)
 26             {
 27                 ++lexer;
 28                 Nfa right;
 29                 if (ParseCatenation(lexercontextright))
 30                 {
 31                     nfa = Alt(contextnfaright);
 32                 }
 33                 else
 34                 {
 35                     lexer.SetPos(save);
 36                     return false;
 37                 }
 38             }
 39             return true;
 40         }
 41         lexer.SetPos(save);
 42         return false;
 43     }
 44     
 45     public bool ParseCatenation(RexLexer& lexerContext& contextNfa& nfa)
 46     {
 47         long save = lexer.GetPos();
 48         if (ParseRepetition(lexercontextnfa))
 49         {
 50             Nfa right;
 51             while (ParseRepetition(lexercontextright))
 52             {
 53                 nfa = Cat(contextnfaright);
 54                 right = Nfa();
 55             }
 56             return true;
 57         }
 58         lexer.SetPos(save);
 59         return false;
 60     }
 61     
 62     public bool ParseRepetition(RexLexer& lexerContext& contextNfa& nfa)
 63     {
 64         long save = lexer.GetPos();
 65         if (ParsePrimary(lexercontextnfa))
 66         {
 67             switch (*lexer)
 68             {
 69                 case STAR:
 70                 {
 71                     ++lexer;
 72                     nfa = Kleene(contextnfa);
 73                     return true;
 74                 }
 75                 case PLUS:
 76                 {
 77                     ++lexer;
 78                     nfa = Pos(contextnfa);
 79                     return true;
 80                 }
 81                 case QUEST:
 82                 {
 83                     ++lexer;
 84                     nfa = Opt(contextnfa);
 85                     return true;
 86                 }
 87             }
 88             return true;
 89         }
 90         lexer.SetPos(save);
 91         return false;
 92     }
 93     
 94     public bool ParsePrimary(RexLexer& lexerContext& contextNfa& nfa)
 95     {
 96         long save = lexer.GetPos();
 97         switch (*lexer)
 98         {
 99             case LPAREN:
100             {
101                 ++lexer;
102                 if (ParseAlternative(lexercontextnfa))
103                 {
104                     if (*lexer == RPAREN)
105                     {
106                         ++lexer;
107                         return true;
108                     }
109                 }
110                 break;
111             }
112             case ESCAPE:
113             {
114                 long pos = lexer.GetPos();
115                 ++lexer;
116                 uchar escape = MakeEscapeValue(lexer.FileName()lexer.GetToken(pos));
117                 nfa = MakeNfa(contextcontext.MakeChar(escape));
118                 return true;
119             }
120             case INVERSE:
121             {
122                 ++lexer;
123                 nfa = MakeNfa(contextcontext.MakeChar('^'));
124                 return true;
125             }
126             case MINUS:
127             {
128                 ++lexer;
129                 nfa = MakeNfa(contextcontext.MakeChar('-'));
130                 return true;
131             }
132             case CHAR:
133             {
134                 long pos = lexer.GetPos();
135                 ++lexer;
136                 uchar ch = lexer.GetUChar(pos);
137                 Symbol* symbol = context.MakeChar(ch);
138                 nfa = MakeNfa(contextsymbol);
139                 return true;
140             }
141             case DOT:
142             {
143                 ++lexer;
144                 nfa = MakeNfa(contextcontext.MakeAny());
145                 return true;
146             }
147             default:
148             {
149                 Class* cls = null;
150                 if (ParseClass(lexercontextcls))
151                 {
152                     nfa = MakeNfa(contextcls);
153                     return true;
154                 }
155                 break;
156             }
157         }
158         lexer.SetPos(save);
159         return false;
160     }
161     
162     public bool ParseClass(RexLexer& lexerContext& contextClass*& cls)
163     {
164         long save = lexer.GetPos();
165         if (*lexer == LBRACKET)
166         {
167             ++lexer;
168             cls = context.MakeClass();
169             if (*lexer == INVERSE)
170             {
171                 Class* invCls = cls;
172                 invCls->SetInverse();
173                 ++lexer;
174             }
175             Symbol* symbol = null;
176             while (ParseRange(lexercontextsymbol))
177             {
178                 Class* symCls = cls;
179                 symCls->AddSymbol(symbol);
180                 symbol = null;
181             }
182             if (*lexer == RBRACKET)
183             {
184                 ++lexer;
185                 return true;
186             }
187         }
188         lexer.SetPos(save);
189         return false;
190     }
191     
192     public bool ParseRange(RexLexer& lexerContext& contextSymbol*& symbol)
193     {
194         long save = lexer.GetPos();
195         uchar s;
196         if (ParseChar(lexercontexts))
197         {
198             if (*lexer == MINUS)
199             {
200                 ++lexer;
201                 uchar e;
202                 if (ParseChar(lexercontexte))
203                 {
204                     symbol = context.MakeRange(se);
205                     return true;
206                 }
207             }
208             else
209             {
210                 symbol = context.MakeChar(s);
211                 return true;
212             }
213         }
214         lexer.SetPos(save);
215         return false;
216     }
217     
218     public bool ParseChar(RexLexer& lexerContext& contextuchar& ch)
219     {
220         long save = lexer.GetPos();
221         switch (*lexer)
222         {
223             case LPAREN:
224             {
225                 ++lexer;
226                 ch = '(';
227                 return true;
228             }
229             case RPAREN:
230             {
231                 ++lexer;
232                 ch = ')';
233                 return true;
234             }
235             case LBRACKET:
236             {
237                 ++lexer;
238                 ch = '[';
239                 return true;
240             }
241             case ALT:
242             {
243                 ++lexer;
244                 ch = '|';
245                 return true;
246             }
247             case STAR:
248             {
249                 ++lexer;
250                 ch = '*';
251                 return true;
252             }
253             case PLUS:
254             {
255                 ++lexer;
256                 ch = '+';
257                 return true;
258             }
259             case QUEST:
260             {
261                 ++lexer;
262                 ch = '?';
263                 return true;
264             }
265             case DOT:
266             {
267                 ++lexer;
268                 ch = '.';
269                 return true;
270             }
271             case ESCAPE:
272             {
273                 long pos = lexer.GetPos();
274                 ++lexer;
275                 ch = MakeEscapeValue(lexer.FileName()lexer.GetToken(pos));
276                 return true;
277             }
278             case INVERSE:
279             {
280                 ++lexer;
281                 ch = '^';
282                 return true;
283             }
284             case MINUS:
285             {
286                 ++lexer;
287                 ch = '-';
288                 return true;
289             }
290             case CHAR:
291             {
292                 long pos = lexer.GetPos();
293                 ++lexer;
294                 ch = lexer.GetUChar(pos);
295                 return true;
296             }
297         }
298         lexer.SetPos(save);
299         return false;
300     }
301 }