3
using MonoDevelop.Projects.Parser;
5
namespace JavaBinding.Parser
8
/// Description of ExpressionFinder.
10
public class ExpressionFinder : IExpressionFinder
12
public string FindExpression(string inText, int offset)
14
this.text = FilterComments(inText, ref offset);
16
this.offset = this.lastAccept = offset;
18
if (this.text == null) {
22
while (state != ERROR) {
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];
27
if (state == ACCEPT || state == ACCEPT2) {
28
lastAccept = this.offset;
30
if (state == ACCEPTNOMORE) {
31
return this.text.Substring(this.offset + 1, offset - this.offset);
34
return this.text.Substring(this.lastAccept + 1, offset - this.lastAccept);
37
#region Comment Filter and 'inside string watcher'
39
public string FilterComments(string text, ref int offset)
41
this.initialOffset = offset;
42
StringBuilder outText = new StringBuilder();
44
while (curOffset <= initialOffset) {
45
char ch = text[curOffset];
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)) {
63
// to read '" and '\" ... this should work for these cases
64
if (curOffset <= initialOffset) {
65
outText.Append(text[curOffset++]);
67
if (curOffset <= initialOffset) {
68
outText.Append(text[curOffset++]);
74
if (!ReadString(outText, text, ref curOffset)) {
79
if (curOffset + 1 < text.Length && text[curOffset + 1] == '/') {
82
if (!ReadToEOL(text, ref curOffset, ref offset)) {
85
} else if (curOffset + 1 < text.Length && text[curOffset + 1] == '*') {
88
if (!ReadMultiLineComment(text, ref curOffset, ref offset)) {
102
return outText.ToString();
105
bool ReadToEOL(string text, ref int curOffset, ref int offset)
107
while (curOffset <= initialOffset) {
108
char ch = text[curOffset++];
117
bool ReadString(StringBuilder outText, string text, ref int curOffset)
119
while (curOffset <= initialOffset) {
120
char ch = text[curOffset++];
124
} else if (ch == '\\') {
125
outText.Append(text[curOffset++]);
131
bool ReadVerbatimString(StringBuilder outText, string text, ref int curOffset)
133
while (curOffset <= initialOffset) {
134
char ch = text[curOffset++];
137
if (curOffset < text.Length && text[curOffset] == '"') {
138
outText.Append(text[curOffset++]);
147
bool ReadMultiLineComment(string text, ref int curOffset, ref int offset)
149
while (curOffset <= initialOffset) {
150
char ch = text[curOffset++];
153
if (curOffset < text.Length && text[curOffset] == '/') {
164
#region mini backward lexer
171
return text[offset--];
189
// tokens for our lexer
192
static int StrLit = 2;
193
static int Ident = 3;
195
static int Bracket = 5;
196
static int Parent = 6;
197
static int Curly = 7;
198
static int Using = 8;
201
string GetTokenName(int state)
203
string[] stateName = new string[] {
204
"Err", "Dot", "StrLit", "Ident", "New", "Bracket", "Paren", "Curly", "Using"
206
return stateName[state];
217
while (Char.IsWhiteSpace(ch)) {
223
if (ReadBracket('{', '}')) {
224
curTokenType = Curly;
228
if (ReadBracket('(', ')')) {
229
curTokenType = Parent;
233
if (ReadBracket('[', ']')) {
234
curTokenType = Bracket;
242
if (ReadStringLiteral(ch)) {
243
curTokenType = StrLit;
247
string ident = ReadIdentifier(ch);
254
curTokenType = Using;
257
curTokenType = Ident;
265
bool ReadStringLiteral(char litStart)
272
if (ch == litStart) {
273
if (Peek() == '@' && litStart == '"') {
281
bool ReadBracket(char openBracket, char closingBracket)
283
int curlyBraceLevel = 0;
284
int squareBracketLevel = 0;
285
int parenthesisLevel = 0;
286
switch (openBracket) {
291
squareBracketLevel++;
298
while (parenthesisLevel != 0 || squareBracketLevel != 0 || curlyBraceLevel != 0) {
308
squareBracketLevel--;
317
squareBracketLevel++;
327
string ReadIdentifier(char ch)
329
string identifier = ch.ToString();
330
while (IsIdentifierPart(Peek())) {
331
identifier = GetNext() + identifier;
336
bool IsIdentifierPart(char ch)
338
return Char.IsLetterOrDigit(ch) || ch == '_';
342
#region finite state machine
343
static int ERROR = 0;
344
static int START = 1;
347
static int CURLY = 4;
348
static int CURLY2 = 5;
349
static int CURLY3 = 6;
351
static int ACCEPT = 7;
352
static int ACCEPTNOMORE = 8;
353
static int ACCEPT2 = 9;
355
string GetStateName(int state)
357
string[] stateName = new string[] {
358
"ERROR", "START", "DOT", "MORE", "CURLY", "CURLY2", "CURLY3", "ACCEPT", "ACCEPTNOMORE", "ACCEPT2"
360
return stateName[state];
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},