~ubuntu-branches/ubuntu/feisty/monodevelop/feisty

« back to all changes in this revision

Viewing changes to Extras/JavaBinding/Parser/ExpressionFinder.cs

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-08-18 00:51:23 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060818005123-5iit07y0j7wjg55f
Tags: 0.11+svn20060818-0ubuntu1
* New SVN snapshot
  + Works with Gtk# 2.9.0
* debian/control:
  + Updated Build-Depends
* debian/patches/use_nunit2.2.dpatch,
  debian/patches/use_real_libs.dpatch:
  + Updated
* debian/patches/versioncontrol_buildfix.dpatch:
  + Fix build failure in the version control addin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
using System;
 
2
using System.Text;
 
3
using MonoDevelop.Projects.Parser;
 
4
 
 
5
namespace JavaBinding.Parser
 
6
{
 
7
        /// <summary>
 
8
        /// Description of ExpressionFinder.    
 
9
        /// </summary>
 
10
        public class ExpressionFinder : IExpressionFinder
 
11
        {
 
12
                public string FindExpression(string inText, int offset)
 
13
                {
 
14
                        this.text = FilterComments(inText, ref offset);
 
15
                        this.text   = text;
 
16
                        this.offset = this.lastAccept = offset;
 
17
                        this.state  = START;
 
18
                        if (this.text == null) {
 
19
                                return null;
 
20
                        }
 
21
                        
 
22
                        while (state != ERROR) {
 
23
                                ReadNextToken();
 
24
                                //Console.WriteLine("cur state {0} got token {1} going to {2}", GetStateName(state), GetTokenName(curTokenType), GetStateName(stateTable[state, curTokenType]));
 
25
                                state = stateTable[state, curTokenType];
 
26
                                
 
27
                                if (state == ACCEPT || state == ACCEPT2) {
 
28
                                        lastAccept = this.offset;
 
29
                                }
 
30
                                if (state == ACCEPTNOMORE) {
 
31
                                        return this.text.Substring(this.offset + 1, offset - this.offset);
 
32
                                }
 
33
                        }
 
34
                        return this.text.Substring(this.lastAccept + 1, offset - this.lastAccept);
 
35
                }
 
36
                
 
37
                #region Comment Filter and 'inside string watcher'
 
38
                int initialOffset;
 
39
                public string FilterComments(string text, ref int offset)
 
40
                {
 
41
                        this.initialOffset = offset;
 
42
                        StringBuilder outText = new StringBuilder();
 
43
                        int curOffset = 0;
 
44
                        while (curOffset <= initialOffset) {
 
45
                                char ch = text[curOffset];
 
46
                                
 
47
                                switch (ch) {
 
48
                                        case '@':
 
49
                                                if (curOffset + 1 < text.Length && text[curOffset + 1] == '"') {
 
50
                                                        outText.Append(text[curOffset++]); // @
 
51
                                                        outText.Append(text[curOffset++]); // "
 
52
                                                        if (!ReadVerbatimString(outText, text, ref curOffset)) {
 
53
                                                                return null;
 
54
                                                        }
 
55
                                                }else{
 
56
                                                        outText.Append(ch);
 
57
                                                        ++curOffset;
 
58
                                                }
 
59
                                                break;
 
60
                                        case '\'':
 
61
                                                outText.Append(ch);
 
62
                                                curOffset++;
 
63
                                                // to read '" and '\" ... this should work for these cases
 
64
                                                if (curOffset <= initialOffset) {
 
65
                                                        outText.Append(text[curOffset++]);
 
66
                                                }
 
67
                                                if (curOffset <= initialOffset) {
 
68
                                                        outText.Append(text[curOffset++]);
 
69
                                                }
 
70
                                                break;
 
71
                                        case '"':
 
72
                                                outText.Append(ch);
 
73
                                                curOffset++;
 
74
                                                if (!ReadString(outText, text, ref curOffset)) {
 
75
                                                        return null;
 
76
                                                }
 
77
                                                break;
 
78
                                        case '/':
 
79
                                                if (curOffset + 1 < text.Length && text[curOffset + 1] == '/') {
 
80
                                                        offset    -= 2;
 
81
                                                        curOffset += 2;
 
82
                                                        if (!ReadToEOL(text, ref curOffset, ref offset)) {
 
83
                                                                return null;
 
84
                                                        }
 
85
                                                } else if (curOffset + 1 < text.Length && text[curOffset + 1] == '*') {
 
86
                                                        offset    -= 2;
 
87
                                                        curOffset += 2;
 
88
                                                        if (!ReadMultiLineComment(text, ref curOffset, ref offset)) {
 
89
                                                                return null;
 
90
                                                        }
 
91
                                                } else {
 
92
                                                        goto default;
 
93
                                                }
 
94
                                                break;
 
95
                                        default:
 
96
                                                outText.Append(ch);
 
97
                                                ++curOffset;
 
98
                                                break;
 
99
                                }
 
100
                        }
 
101
                        
 
102
                        return outText.ToString();
 
103
                }
 
104
                
 
105
                bool ReadToEOL(string text, ref int curOffset, ref int offset)
 
106
                {
 
107
                        while (curOffset <= initialOffset) {
 
108
                                char ch = text[curOffset++];
 
109
                                --offset;
 
110
                                if (ch == '\n') {
 
111
                                        return true;
 
112
                                }
 
113
                        }
 
114
                        return false;
 
115
                }
 
116
                
 
117
                bool ReadString(StringBuilder outText, string text, ref int curOffset)
 
118
                {
 
119
                        while (curOffset <= initialOffset) {
 
120
                                char ch = text[curOffset++];
 
121
                                outText.Append(ch);
 
122
                                if (ch == '"') {
 
123
                                        return true;
 
124
                                } else if (ch == '\\') {
 
125
                                        outText.Append(text[curOffset++]);
 
126
                                }
 
127
                        }
 
128
                        return false;
 
129
                }
 
130
                
 
131
                bool ReadVerbatimString(StringBuilder outText, string text, ref int curOffset)
 
132
                {
 
133
                        while (curOffset <= initialOffset) {
 
134
                                char ch = text[curOffset++];
 
135
                                outText.Append(ch);
 
136
                                if (ch == '"') {
 
137
                                        if (curOffset < text.Length && text[curOffset] == '"') {
 
138
                                                outText.Append(text[curOffset++]);
 
139
                                        } else {
 
140
                                                return true;
 
141
                                        }
 
142
                                }
 
143
                        }
 
144
                        return false;
 
145
                }
 
146
                
 
147
                bool ReadMultiLineComment(string text, ref int curOffset, ref int offset)
 
148
                {
 
149
                        while (curOffset <= initialOffset) {
 
150
                                char ch = text[curOffset++];
 
151
                                --offset;
 
152
                                if (ch == '*') {
 
153
                                        if (curOffset < text.Length && text[curOffset] == '/') {
 
154
                                                ++curOffset;
 
155
                                                --offset;
 
156
                                                return true;
 
157
                                        }
 
158
                                }
 
159
                        }
 
160
                        return false;
 
161
                }
 
162
                #endregion
 
163
                
 
164
                #region mini backward lexer
 
165
                string text;
 
166
                int    offset;
 
167
                
 
168
                char GetNext()
 
169
                {
 
170
                        if (offset >= 0) {
 
171
                                return text[offset--];
 
172
                        }
 
173
                        return '\0';
 
174
                }
 
175
                
 
176
                char Peek()
 
177
                {
 
178
                        if (offset >= 0) {
 
179
                                return text[offset];
 
180
                        }
 
181
                        return '\0';
 
182
                }
 
183
                
 
184
                void UnGet()
 
185
                {
 
186
                        ++offset;
 
187
                }
 
188
                
 
189
                // tokens for our lexer
 
190
                static int Err     = 0;
 
191
                static int Dot     = 1;
 
192
                static int StrLit  = 2;
 
193
                static int Ident   = 3;
 
194
                static int New     = 4;
 
195
                static int Bracket = 5;
 
196
                static int Parent  = 6;
 
197
                static int Curly   = 7;
 
198
                static int Using   = 8;
 
199
                int curTokenType;
 
200
                
 
201
                string GetTokenName(int state)
 
202
                {
 
203
                        string[] stateName = new string[] {
 
204
                                "Err", "Dot", "StrLit", "Ident", "New", "Bracket", "Paren", "Curly", "Using"
 
205
                        };
 
206
                        return stateName[state];
 
207
                }
 
208
                
 
209
                void ReadNextToken()
 
210
                {
 
211
                        char ch = GetNext();
 
212
                                
 
213
                        curTokenType = Err;
 
214
                        if (ch == '\0') {
 
215
                                return;
 
216
                        }
 
217
                        while (Char.IsWhiteSpace(ch)) {
 
218
                                ch = GetNext();
 
219
                        }
 
220
                        
 
221
                        switch (ch) {
 
222
                                case '}':
 
223
                                        if (ReadBracket('{', '}')) {
 
224
                                                curTokenType = Curly;
 
225
                                        }
 
226
                                        break;
 
227
                                case ')':
 
228
                                        if (ReadBracket('(', ')')) {
 
229
                                                curTokenType = Parent;
 
230
                                        }
 
231
                                        break;
 
232
                                case ']':
 
233
                                        if (ReadBracket('[', ']')) {
 
234
                                                curTokenType = Bracket;
 
235
                                        }
 
236
                                        break;
 
237
                                case '.':
 
238
                                        curTokenType = Dot;
 
239
                                        break;
 
240
                                case '\'':
 
241
                                case '"':
 
242
                                        if (ReadStringLiteral(ch)) {
 
243
                                                curTokenType = StrLit;
 
244
                                        }
 
245
                                        break;
 
246
                                default:
 
247
                                        string ident = ReadIdentifier(ch);
 
248
                                        if (ident != null) {
 
249
                                                switch (ident) {
 
250
                                                        case "new":
 
251
                                                                curTokenType = New;
 
252
                                                                break;
 
253
                                                        case "using":
 
254
                                                                curTokenType = Using;
 
255
                                                                break;
 
256
                                                        default:
 
257
                                                                curTokenType = Ident;
 
258
                                                                break;
 
259
                                                }
 
260
                                        }
 
261
                                        break;
 
262
                        }
 
263
                }
 
264
                
 
265
                bool ReadStringLiteral(char litStart)
 
266
                {
 
267
                        while (true) {
 
268
                                char ch = GetNext();
 
269
                                if (ch == '\0') {
 
270
                                        return false;
 
271
                                }
 
272
                                if (ch == litStart) {
 
273
                                        if (Peek() == '@' && litStart == '"') {
 
274
                                                GetNext();
 
275
                                        }
 
276
                                        return true;
 
277
                                }
 
278
                        }
 
279
                }
 
280
                
 
281
                bool ReadBracket(char openBracket, char closingBracket)
 
282
                {
 
283
                        int curlyBraceLevel    = 0;
 
284
                        int squareBracketLevel = 0;
 
285
                        int parenthesisLevel   = 0;
 
286
                        switch (openBracket) {
 
287
                                case '(':
 
288
                                        parenthesisLevel++;
 
289
                                        break;
 
290
                                case '[':
 
291
                                        squareBracketLevel++;
 
292
                                        break;
 
293
                                case '{':
 
294
                                        curlyBraceLevel++;
 
295
                                        break;
 
296
                        }
 
297
                        
 
298
                        while (parenthesisLevel != 0 || squareBracketLevel != 0 || curlyBraceLevel != 0) {
 
299
                                char ch = GetNext();
 
300
                                if (ch == '\0') {
 
301
                                        return false;
 
302
                                }
 
303
                                switch (ch) {
 
304
                                        case '(':
 
305
                                                parenthesisLevel--;
 
306
                                                break;
 
307
                                        case '[':
 
308
                                                squareBracketLevel--;
 
309
                                                break;
 
310
                                        case '{':
 
311
                                                curlyBraceLevel--;
 
312
                                                break;
 
313
                                        case ')':
 
314
                                                parenthesisLevel++;
 
315
                                                break;
 
316
                                        case ']':
 
317
                                                squareBracketLevel++;
 
318
                                                break;
 
319
                                        case '}':
 
320
                                                curlyBraceLevel++;
 
321
                                                break;
 
322
                                }
 
323
                        }
 
324
                        return true;
 
325
                }
 
326
                
 
327
                string ReadIdentifier(char ch)
 
328
                {
 
329
                        string identifier = ch.ToString();
 
330
                        while (IsIdentifierPart(Peek())) {
 
331
                                identifier = GetNext() + identifier;
 
332
                        }
 
333
                        return identifier;
 
334
                }
 
335
                
 
336
                bool IsIdentifierPart(char ch)
 
337
                {
 
338
                        return Char.IsLetterOrDigit(ch) || ch == '_';
 
339
                }
 
340
                #endregion
 
341
                
 
342
                #region finite state machine 
 
343
                static int ERROR  = 0;
 
344
                static int START  = 1;
 
345
                static int DOT    = 2;
 
346
                static int MORE   = 3;
 
347
                static int CURLY  = 4;
 
348
                static int CURLY2 = 5;
 
349
                static int CURLY3 = 6;
 
350
                
 
351
                static int ACCEPT = 7;
 
352
                static int ACCEPTNOMORE = 8;
 
353
                static int ACCEPT2 = 9;
 
354
                
 
355
                string GetStateName(int state)
 
356
                {
 
357
                        string[] stateName = new string[] {
 
358
                                "ERROR", "START", "DOT", "MORE", "CURLY", "CURLY2", "CURLY3", "ACCEPT", "ACCEPTNOMORE", "ACCEPT2"
 
359
                        };
 
360
                        return stateName[state];
 
361
                }
 
362
                
 
363
                int state = 0;
 
364
                int lastAccept = 0;
 
365
                static int[,] stateTable = new int[,] {
 
366
                        //                   Err,     Dot,     Str,      ID,         New,     Brk,     Par,     Cur,   Using
 
367
                        /*ERROR*/        { ERROR,   ERROR,   ERROR,   ERROR,        ERROR,  ERROR,   ERROR,   ERROR,   ERROR},
 
368
                        /*START*/        { ERROR,     DOT,  ACCEPT,  ACCEPT,        ERROR,   MORE, ACCEPT2,   CURLY,   ACCEPTNOMORE},
 
369
                        /*DOT*/          { ERROR,   ERROR,  ACCEPT,  ACCEPT,        ERROR,   MORE,  ACCEPT,   CURLY,   ERROR},
 
370
                        /*MORE*/         { ERROR,   ERROR,  ACCEPT,  ACCEPT,        ERROR,   MORE, ACCEPT2,   CURLY,   ERROR},
 
371
                        /*CURLY*/        { ERROR,   ERROR,   ERROR,   ERROR,        ERROR, CURLY2,   ERROR,   ERROR,   ERROR},
 
372
                        /*CURLY2*/       { ERROR,   ERROR,   ERROR,  CURLY3,        ERROR,  ERROR,   ERROR,   ERROR,   ERROR},
 
373
                        /*CURLY3*/       { ERROR,   ERROR,   ERROR,   ERROR, ACCEPTNOMORE,  ERROR,   ERROR,   ERROR,   ERROR},
 
374
                        /*ACCEPT*/       { ERROR,    MORE,   ERROR,   ERROR,       ACCEPT,  ERROR,   ERROR,   ERROR,   ACCEPTNOMORE},
 
375
                        /*ACCEPTNOMORE*/ { ERROR,   ERROR,   ERROR,   ERROR,        ERROR,  ERROR,   ERROR,   ERROR,   ERROR},
 
376
                        /*ACCEPT2*/      { ERROR,    MORE,   ERROR,  ACCEPT,       ACCEPT,  ERROR,   ERROR,   ERROR,   ERROR},
 
377
                };
 
378
                #endregion 
 
379
        }
 
380
}