~ubuntu-branches/ubuntu/trusty/anjuta/trusty

« back to all changes in this revision

Viewing changes to plugins/language-support-cpp-java/cxxparser/engine-parser.cpp

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2012-08-17 23:48:26 UTC
  • mfrom: (1.1.50)
  • Revision ID: package-import@ubuntu.com-20120817234826-fvk3rfp6nmfaqi9p
Tags: 2:3.5.5-0ubuntu1
* New upstream release.
* debian/control.in:
  - Bump vala dependency to 0.18 series
  - Drop graphviz from build-depends
* debian/watch: Watch for unstable releases

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2
 
/*
3
 
 * anjuta
4
 
 * Copyright (C) Eran Ifrah (Main file for CodeLite www.codelite.org/ )
5
 
 * Copyright (C) Massimo Cora' 2009 <maxcvs@email.it>
6
 
 * 
7
 
 * anjuta is free software: you can redistribute it and/or modify it
8
 
 * under the terms of the GNU General Public License as published by the
9
 
 * Free Software Foundation, either version 3 of the License, or
10
 
 * (at your option) any later version.
11
 
 * 
12
 
 * anjuta is distributed in the hope that it will be useful, but
13
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 
 * See the GNU General Public License for more details.
16
 
 * 
17
 
 * You should have received a copy of the GNU General Public License along
18
 
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 
 */
20
 
 
21
 
#include <libanjuta/anjuta-debug.h>
22
 
#include <string>
23
 
#include <vector>
24
 
#include <libanjuta/interfaces/ianjuta-symbol-query.h>
25
 
#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
26
 
 
27
 
#include "engine-parser-priv.h"
28
 
#include "engine-parser.h"
29
 
#include "flex-lexer-klass-tab.h"
30
 
#include "expression-parser.h"
31
 
#include "scope-parser.h"
32
 
#include "variable-parser.h"
33
 
#include "function-parser.h"
34
 
 
35
 
 
36
 
 
37
 
using namespace std;
38
 
 
39
 
/* Singleton pattern. */
40
 
EngineParser* 
41
 
EngineParser::getInstance ()
42
 
{
43
 
        if (s_engine == NULL)
44
 
        {
45
 
                s_engine = new EngineParser ();
46
 
        }
47
 
 
48
 
        return s_engine;
49
 
}
50
 
 
51
 
EngineParser::EngineParser ()
52
 
{       
53
 
        _main_tokenizer = new CppTokenizer ();  
54
 
        _extra_tokenizer = new CppTokenizer (); 
55
 
}
56
 
 
57
 
EngineParser::~EngineParser ()
58
 
{
59
 
        delete _main_tokenizer;
60
 
        delete _extra_tokenizer;
61
 
}
62
 
 
63
 
bool 
64
 
EngineParser::nextMainToken (string &out_token, string &out_delimiter)
65
 
{
66
 
        out_token.clear ();
67
 
        
68
 
        int type(0);
69
 
        int depth(0);
70
 
        while ( (type = _main_tokenizer->yylex()) != 0 ) 
71
 
        {               
72
 
                switch (type) 
73
 
                {                       
74
 
                case CLCL:
75
 
                case '.':
76
 
                case lexARROW:
77
 
                        if (depth == 0) 
78
 
                        {
79
 
                                out_delimiter = _main_tokenizer->YYText();
80
 
                                trim (out_token);
81
 
                                return true;
82
 
                        } else 
83
 
                        {
84
 
                                out_token.append (" ").append (_main_tokenizer->YYText());
85
 
                        }
86
 
                        break;
87
 
                                
88
 
                case '<':
89
 
                case '[':
90
 
                case '(':
91
 
                case '{':
92
 
                        depth++;
93
 
                        out_token.append (" ").append (_main_tokenizer->YYText());
94
 
                        break;
95
 
                                
96
 
                case '>':
97
 
                case ']':
98
 
                case ')':
99
 
                case '}':
100
 
                        depth--;
101
 
                        out_token.append (" ").append (_main_tokenizer->YYText());
102
 
                        break;
103
 
                                
104
 
                default:
105
 
                        out_token.append (" ").append (_main_tokenizer->YYText());
106
 
                        break;
107
 
                }
108
 
        }
109
 
        trim (out_token);
110
 
        return false;
111
 
}
112
 
 
113
 
ExpressionResult 
114
 
EngineParser::parseExpression(const string &in)
115
 
{
116
 
        return parse_expression (in.c_str ());  
117
 
}
118
 
 
119
 
void
120
 
EngineParser::unsetSymbolManager ()
121
 
{
122
 
        if (_query_scope)
123
 
                g_object_unref (_query_scope);
124
 
        _query_scope = NULL;
125
 
 
126
 
        if (_query_search)
127
 
                g_object_unref (_query_search);
128
 
        _query_search = NULL;
129
 
 
130
 
        if (_query_search_in_scope)
131
 
                g_object_unref (_query_search_in_scope);
132
 
        _query_search_in_scope = NULL;
133
 
 
134
 
        if (_query_parent_scope)
135
 
                g_object_unref (_query_parent_scope);
136
 
        _query_parent_scope = NULL;
137
 
}
138
 
 
139
 
void 
140
 
EngineParser::setSymbolManager (IAnjutaSymbolManager *manager)
141
 
{
142
 
        static IAnjutaSymbolField query_parent_scope_fields[] =
143
 
        {
144
 
                IANJUTA_SYMBOL_FIELD_ID, IANJUTA_SYMBOL_FIELD_NAME,
145
 
                IANJUTA_SYMBOL_FIELD_KIND, IANJUTA_SYMBOL_FIELD_TYPE
146
 
        };
147
 
        static IAnjutaSymbolField query_search_fields[] =
148
 
        {
149
 
                IANJUTA_SYMBOL_FIELD_ID, IANJUTA_SYMBOL_FIELD_NAME,
150
 
                IANJUTA_SYMBOL_FIELD_KIND
151
 
        };
152
 
        static IAnjutaSymbolField query_scope_fields[] =
153
 
        {
154
 
                IANJUTA_SYMBOL_FIELD_ID, IANJUTA_SYMBOL_FIELD_NAME,
155
 
                IANJUTA_SYMBOL_FIELD_SIGNATURE, IANJUTA_SYMBOL_FIELD_TYPE
156
 
        };
157
 
        static IAnjutaSymbolField query_search_in_scope_fields[] =
158
 
        {
159
 
                IANJUTA_SYMBOL_FIELD_ID, IANJUTA_SYMBOL_FIELD_NAME,
160
 
                IANJUTA_SYMBOL_FIELD_KIND, IANJUTA_SYMBOL_FIELD_RETURNTYPE,
161
 
                IANJUTA_SYMBOL_FIELD_SIGNATURE, IANJUTA_SYMBOL_FIELD_TYPE_NAME
162
 
        };
163
 
        _query_search =
164
 
                ianjuta_symbol_manager_create_query (manager,
165
 
                                                     IANJUTA_SYMBOL_QUERY_SEARCH,
166
 
                                                     IANJUTA_SYMBOL_QUERY_DB_PROJECT, NULL);
167
 
        ianjuta_symbol_query_set_filters (_query_search,
168
 
                                          (IAnjutaSymbolType)
169
 
                                          (IANJUTA_SYMBOL_TYPE_SCOPE_CONTAINER |
170
 
                                           IANJUTA_SYMBOL_TYPE_TYPEDEF), TRUE, NULL);
171
 
        ianjuta_symbol_query_set_fields (_query_search,
172
 
                                         G_N_ELEMENTS (query_search_fields),
173
 
                                         query_search_fields, NULL);
174
 
        _query_scope =
175
 
                ianjuta_symbol_manager_create_query (manager,
176
 
                                                     IANJUTA_SYMBOL_QUERY_SEARCH_SCOPE,
177
 
                                                     IANJUTA_SYMBOL_QUERY_DB_PROJECT, NULL);
178
 
        ianjuta_symbol_query_set_fields (_query_scope,
179
 
                                         G_N_ELEMENTS (query_scope_fields),
180
 
                                         query_scope_fields, NULL);
181
 
        _query_search_in_scope =
182
 
                ianjuta_symbol_manager_create_query (manager,
183
 
                                                     IANJUTA_SYMBOL_QUERY_SEARCH_IN_SCOPE,
184
 
                                                     IANJUTA_SYMBOL_QUERY_DB_PROJECT, NULL);
185
 
        ianjuta_symbol_query_set_fields (_query_search_in_scope,
186
 
                                         G_N_ELEMENTS (query_search_in_scope_fields),
187
 
                                         query_search_in_scope_fields, NULL);
188
 
        _query_parent_scope =
189
 
                ianjuta_symbol_manager_create_query (manager,
190
 
                                                     IANJUTA_SYMBOL_QUERY_SEARCH_PARENT_SCOPE,
191
 
                                                     IANJUTA_SYMBOL_QUERY_DB_PROJECT, NULL);
192
 
        ianjuta_symbol_query_set_fields (_query_parent_scope,
193
 
                                         G_N_ELEMENTS (query_parent_scope_fields),
194
 
                                         query_parent_scope_fields, NULL);
195
 
}
196
 
 
197
 
void 
198
 
EngineParser::trim (string& str, string trimChars /* = "{};\r\n\t\v " */)
199
 
{
200
 
        string::size_type pos = str.find_last_not_of (trimChars);
201
 
        
202
 
        if (pos != string::npos) 
203
 
        {
204
 
        str.erase(pos + 1);
205
 
        pos = str.find_first_not_of (trimChars);
206
 
        if(pos != string::npos) 
207
 
                {                       
208
 
                          str.erase(0, pos);
209
 
                }
210
 
        }
211
 
        else 
212
 
        {
213
 
                str.erase(str.begin(), str.end());
214
 
        }
215
 
}
216
 
 
217
 
/**
218
 
 * @return NULL on global 
219
 
 */
220
 
void
221
 
EngineParser::getNearestClassInCurrentScopeChainByFileLine (const char* full_file_path, 
222
 
                                                            unsigned long linenum,
223
 
                                                            string &out_type_name)
224
 
{
225
 
        IAnjutaIterable *iter;
226
 
 
227
 
        /* Find current scope of given file and line */
228
 
        iter = ianjuta_symbol_query_search_scope (_query_scope, full_file_path,
229
 
                                                  linenum, NULL);
230
 
        if (iter == NULL)
231
 
                return;
232
 
 
233
 
        /* FIXME: this method doesn't take into consideration 
234
 
         * classes with same name on multiple namespaces 
235
 
         */
236
 
        if (iter != NULL)
237
 
        {
238
 
                do 
239
 
                {
240
 
                        IAnjutaIterable *parent_iter;
241
 
                        IAnjutaSymbol *node = IANJUTA_SYMBOL (iter);
242
 
                        DEBUG_PRINT ("sym_name = %s", ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_NAME, NULL));
243
 
                        if (ianjuta_symbol_get_sym_type (node, NULL) == IANJUTA_SYMBOL_TYPE_CLASS)
244
 
                        {
245
 
                                out_type_name = ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_NAME, NULL);
246
 
                                break;
247
 
                        }
248
 
                        parent_iter =
249
 
                                ianjuta_symbol_query_search_parent_scope (_query_parent_scope,
250
 
                                                                          node, NULL);
251
 
 
252
 
                        if (parent_iter && 
253
 
                            ianjuta_symbol_get_int (IANJUTA_SYMBOL (iter), IANJUTA_SYMBOL_FIELD_ID, NULL) == 
254
 
                            ianjuta_symbol_get_int (IANJUTA_SYMBOL (parent_iter), IANJUTA_SYMBOL_FIELD_ID, NULL))
255
 
                        {
256
 
                                g_object_unref (parent_iter);
257
 
                                break;
258
 
                        }                           
259
 
                        
260
 
                        g_object_unref (iter);
261
 
                        iter = parent_iter;
262
 
                } while (iter);
263
 
                if (iter)
264
 
                        g_object_unref (iter);
265
 
        }
266
 
}
267
 
 
268
 
bool
269
 
EngineParser::getTypeNameAndScopeByToken (ExpressionResult &result, 
270
 
                                                                          string &token,
271
 
                                                                          string &op,
272
 
                                                                          const string& full_file_path, 
273
 
                                                                          unsigned long linenum,
274
 
                                                                          const string& above_text,
275
 
                                                                          string &out_type_name, 
276
 
                                                                          string &out_type_scope)
277
 
{
278
 
        if (result.m_isaType) 
279
 
        {
280
 
                DEBUG_PRINT ("*** Found a cast expression");
281
 
                /*
282
 
                 * Handle type (usually when casting is found)
283
 
                 */
284
 
                if (result.m_isPtr && op == ".") 
285
 
                {
286
 
                        DEBUG_PRINT ("Did you mean to use '->' instead of '.' ?");
287
 
                        return false;
288
 
                }
289
 
                
290
 
                if (!result.m_isPtr && op == "->") 
291
 
                {
292
 
                        DEBUG_PRINT ("Can not use '->' operator on a non pointer object");
293
 
                        return false;
294
 
                }
295
 
 
296
 
                out_type_scope = result.m_scope.empty() ? "" : result.m_scope.c_str();
297
 
                out_type_name = result.m_name.c_str();
298
 
                return true;
299
 
        } 
300
 
        else if (result.m_isThis) 
301
 
        {
302
 
                DEBUG_PRINT ("*** Found 'this'");
303
 
                
304
 
                /* special handle for 'this' keyword */
305
 
                if (op == "::") 
306
 
                {
307
 
                        DEBUG_PRINT ("'this' can not be used with operator ::");
308
 
                        return false;
309
 
                }
310
 
 
311
 
                if (result.m_isPtr && op == ".") 
312
 
                {
313
 
                        DEBUG_PRINT ("Did you mean to use '->' instead of '.' ?");
314
 
                        return false;
315
 
                }
316
 
                        
317
 
                if (!result.m_isPtr && op == "->") 
318
 
                {
319
 
                        DEBUG_PRINT ("Can not use '->' operator on a non pointer object");
320
 
                        return false;
321
 
                }
322
 
 
323
 
                /* reaching this point we are quite sure that the easiest tests about "this"
324
 
                 * calling are passed. Go on finding for the first symbol of type class that
325
 
                 * is reachable through the scopes chain.
326
 
                 */     
327
 
 
328
 
                /* will we find a good class scope? */
329
 
                out_type_scope = result.m_scope.empty() ? "" : result.m_scope.c_str();
330
 
                out_type_name = ""; 
331
 
 
332
 
                getNearestClassInCurrentScopeChainByFileLine (full_file_path.c_str (), linenum, out_type_name);
333
 
                if (out_type_name.empty ()) 
334
 
                {
335
 
                        DEBUG_PRINT ("'this' has not a type name");
336
 
                        return false;
337
 
                }
338
 
                
339
 
                return true;
340
 
        }
341
 
        else if (op == "::")
342
 
        {
343
 
                out_type_name = token;
344
 
                out_type_scope = result.m_scope.empty() ? "" : result.m_scope.c_str();
345
 
                return true;
346
 
        }
347
 
        else 
348
 
        {
349
 
                /*
350
 
                 * Found an identifier (can be a local variable, a global one etc)
351
 
                 */                     
352
 
                DEBUG_PRINT ("*** Found an identifier or local variable...");
353
 
 
354
 
                /* optimize scope'll clear the scopes leaving the local variables */
355
 
                string optimized_scope = optimizeScope(above_text);
356
 
 
357
 
                VariableList li;
358
 
                std::map<std::string, std::string> ignoreTokens;
359
 
                get_variables(optimized_scope, li, ignoreTokens, false);
360
 
 
361
 
                /* here the trick is to start from the end of the found variables
362
 
                 * up to the begin. This because the local variable declaration should be found
363
 
                 * just above to the statement line 
364
 
                 */
365
 
                for (VariableList::reverse_iterator iter = li.rbegin(); iter != li.rend(); iter++) 
366
 
                {
367
 
                        Variable var = (*iter);
368
 
                
369
 
                        if (token == var.m_name) 
370
 
                        {
371
 
                                DEBUG_PRINT ("We found the variable type to parse... it's \"%s"
372
 
                                        "\" with typescope \"%s\"", var.m_type.c_str(), var.m_typeScope.c_str());
373
 
                                out_type_name = var.m_type;
374
 
                                out_type_scope = var.m_typeScope;
375
 
 
376
 
                                return true;
377
 
                        }
378
 
                }
379
 
 
380
 
                IAnjutaIterable* curr_scope_iter = 
381
 
                        ianjuta_symbol_query_search_scope (_query_scope,
382
 
                                                           full_file_path.c_str (),
383
 
                                                           linenum, NULL);
384
 
 
385
 
                if (curr_scope_iter != NULL)
386
 
                {
387
 
                        IAnjutaSymbol *node = IANJUTA_SYMBOL (curr_scope_iter);
388
 
 
389
 
                        /* try to get the signature from the symbol and test if the 
390
 
                         * variable searched is found there.
391
 
                         */
392
 
                        const gchar * signature = ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_SIGNATURE, NULL);
393
 
                        if (signature == NULL)
394
 
                        {
395
 
                                g_object_unref (curr_scope_iter);
396
 
                                return false;
397
 
                        }
398
 
                        
399
 
                        DEBUG_PRINT ("Signature is %s", signature);
400
 
 
401
 
                        get_variables(signature, li, ignoreTokens, false);
402
 
                        
403
 
                        for (VariableList::reverse_iterator iter = li.rbegin(); iter != li.rend(); iter++) 
404
 
                        {
405
 
                                Variable var = (*iter);
406
 
                        
407
 
                                if (token == var.m_name) 
408
 
                                {
409
 
                                DEBUG_PRINT ("We found the variable type to parse from signature... it's \"%s"
410
 
                                        "\" with typescope \"%s\"", var.m_type.c_str (), var.m_typeScope.c_str ());
411
 
                                        out_type_name = var.m_type;
412
 
                                        out_type_scope = var.m_typeScope;
413
 
 
414
 
                                        g_object_unref (curr_scope_iter);
415
 
                                        return true;
416
 
                                }
417
 
                        }                       
418
 
 
419
 
                        g_object_unref (curr_scope_iter);
420
 
                }
421
 
                
422
 
                /* if we reach this point it's likely that we missed the right var type */
423
 
                DEBUG_PRINT ("## Wrong detection of the variable type");
424
 
        }
425
 
        return false;
426
 
}
427
 
 
428
 
/**
429
 
 * Find a searchable scope (or container) from a type_name and type_scope strings.
430
 
 * This function should usually be used to determine first token's scope.
431
 
 */
432
 
IAnjutaIterable *
433
 
EngineParser::getCurrentSearchableScope (string &type_name, string &type_scope)
434
 
{
435
 
        // FIXME: case of more results now it's hardcoded to 1
436
 
        IAnjutaIterable *curr_searchable_scope =
437
 
                ianjuta_symbol_query_search (_query_search, type_name.c_str(), NULL);
438
 
        
439
 
        if (curr_searchable_scope != NULL)
440
 
        {
441
 
                IAnjutaSymbol *node;
442
 
 
443
 
                node = IANJUTA_SYMBOL (curr_searchable_scope);
444
 
 
445
 
                const gchar *skind = ianjuta_symbol_get_string (node,
446
 
                                                        IANJUTA_SYMBOL_FIELD_KIND, NULL);
447
 
                
448
 
                DEBUG_PRINT ("Current Searchable Scope name \"%s\" kind \"%s\" and id %d",
449
 
                             ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_NAME, NULL), skind,
450
 
                             ianjuta_symbol_get_int (node, IANJUTA_SYMBOL_FIELD_ID, NULL));
451
 
 
452
 
                /* is it a typedef? In that case find the parent struct */
453
 
                if (g_strcmp0 (ianjuta_symbol_get_string (node,
454
 
                    IANJUTA_SYMBOL_FIELD_KIND, NULL), "typedef") == 0)
455
 
                {
456
 
                        DEBUG_PRINT ("It's a TYPEDEF... trying to find the associated struct...!");
457
 
 
458
 
                        curr_searchable_scope = switchTypedefToStruct (IANJUTA_ITERABLE (node));
459
 
                        
460
 
                        node = IANJUTA_SYMBOL (curr_searchable_scope);
461
 
                        DEBUG_PRINT ("(NEW) Current Searchable Scope %s and id %d",
462
 
                                                ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_NAME, NULL), 
463
 
                                                ianjuta_symbol_get_int (node, IANJUTA_SYMBOL_FIELD_ID, NULL));
464
 
                }
465
 
        }
466
 
        else
467
 
        {
468
 
                DEBUG_PRINT ("Current Searchable Scope NULL");
469
 
        }
470
 
 
471
 
        return curr_searchable_scope;
472
 
}
473
 
 
474
 
/**
475
 
 * @param test Must be searched with SYMINFO_KIND 
476
 
 * @return or the same test iterator or a new struct. In that second case the input 
477
 
 * iterator test is unreffed.
478
 
 * 
479
 
 */
480
 
IAnjutaIterable *
481
 
EngineParser::switchTypedefToStruct (IAnjutaIterable * test,
482
 
                                                 IAnjutaSymbolField sym_info 
483
 
                                     /*= (SymExtraInfo)(SYMINFO_SIMPLE | SYMINFO_KIND)*/)
484
 
{
485
 
        IAnjutaSymbol *node = IANJUTA_SYMBOL (test);    
486
 
        IAnjutaIterable *new_struct;
487
 
 
488
 
        DEBUG_PRINT ("Switching TYPEDEF (%d) ==> to STRUCT",
489
 
                     ianjuta_symbol_get_int (node, IANJUTA_SYMBOL_FIELD_ID, NULL));
490
 
        new_struct = ianjuta_symbol_query_search_parent_scope (_query_parent_scope,
491
 
                                                               node, NULL);
492
 
                                                 
493
 
        if (new_struct != NULL)
494
 
        {
495
 
                /* kill the old one */
496
 
                g_object_unref (test);
497
 
 
498
 
                test = new_struct;
499
 
        }
500
 
        else 
501
 
        {
502
 
                DEBUG_PRINT ("Couldn't find a parent for typedef. We'll return the same object");
503
 
        }       
504
 
 
505
 
        return test;
506
 
}
507
 
 
508
 
IAnjutaIterable *
509
 
EngineParser::switchMemberToContainer (IAnjutaIterable * test)
510
 
{
511
 
        IAnjutaSymbol *node = IANJUTA_SYMBOL (test);    
512
 
        IAnjutaIterable *new_container;
513
 
        const gchar* sym_type_name =
514
 
                ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_TYPE_NAME, NULL);
515
 
 
516
 
        DEBUG_PRINT ("Switching container with type_name %s", sym_type_name);
517
 
 
518
 
        /* hopefully we'll find a new container for the type_name of test param */
519
 
        new_container = ianjuta_symbol_query_search (_query_search,
520
 
                                                     sym_type_name, NULL);
521
 
        if (new_container != NULL)
522
 
        {
523
 
                g_object_unref (test);
524
 
 
525
 
                test = new_container;
526
 
 
527
 
                DEBUG_PRINT (".. found new container with n items %d", 
528
 
                             ianjuta_iterable_get_length (test, NULL));
529
 
        }
530
 
        else 
531
 
        {
532
 
                DEBUG_PRINT ("Couldn't find a container to substitute sym_type_name %s",
533
 
                             sym_type_name);
534
 
        }       
535
 
 
536
 
        return test;
537
 
}
538
 
 
539
 
/* FIXME TODO: error processing. Find out a way to notify the caller of the occurred 
540
 
 * error. The "cout" method cannot be used
541
 
 */
542
 
IAnjutaIterable *
543
 
EngineParser::processExpression(const string& stmt, 
544
 
                                                        const string& above_text,
545
 
                                                        const string& full_file_path, 
546
 
                                                        unsigned long linenum)
547
 
{
548
 
        ExpressionResult result;
549
 
        string current_token;
550
 
        string op;
551
 
        string type_name;
552
 
        string type_scope;
553
 
 
554
 
        DEBUG_PRINT ("Setting text %s to the tokenizer", stmt.c_str ());
555
 
        _main_tokenizer->setText (stmt.c_str ());
556
 
 
557
 
        /* get the first token */
558
 
        nextMainToken (current_token, op);              
559
 
 
560
 
        DEBUG_PRINT ("First main token \"%s\" with op \"%s\"", current_token.c_str (), op.c_str ());
561
 
 
562
 
        /* parse the current sub-expression of a statement and fill up 
563
 
         * ExpressionResult object
564
 
         */
565
 
        result = parseExpression (current_token);
566
 
 
567
 
        /* fine. Get the type name and type scope given the above result for the first 
568
 
         * and most important token.
569
 
         * The type_scope is for instance 'std' in this statement:
570
 
         * (std::foo_util)klass->
571
 
         */     
572
 
        bool process_res = getTypeNameAndScopeByToken (result, 
573
 
                                                                          current_token,
574
 
                                                                          op,
575
 
                                                                          full_file_path, 
576
 
                                                                          linenum,
577
 
                                                                          above_text,
578
 
                                                                          type_name, 
579
 
                                                                          type_scope);
580
 
        if (process_res == false)
581
 
        {
582
 
                DEBUG_PRINT ("Initial statement processing failed. "
583
 
                        "I cannot continue. ");
584
 
                return NULL;
585
 
        }
586
 
        
587
 
        DEBUG_PRINT ("Searching for curr_searchable_scope with type_name \"%s\""
588
 
                                " and type_scope \"%s\"", type_name.c_str (), type_scope.c_str ());
589
 
 
590
 
        /* at this time we're enough ready to issue a first query to our db. 
591
 
         * We absolutely need to find the searchable object scope of the first result 
592
 
         * type. By this one we can iterate the tree of scopes and reach a result.
593
 
         */     
594
 
        IAnjutaIterable *curr_searchable_scope =
595
 
                getCurrentSearchableScope (type_name, type_scope);
596
 
 
597
 
        if (curr_searchable_scope == NULL)
598
 
        {
599
 
                DEBUG_PRINT ("curr_searchable_scope failed to process, check the problem please");
600
 
                return NULL;
601
 
        }       
602
 
        
603
 
        /* fine. Have we more tokens left? */
604
 
        while (nextMainToken (current_token, op) == 1) 
605
 
        {
606
 
                DEBUG_PRINT("Next main token \"%s\" with op \"%s\"",current_token.c_str (), op.c_str ());
607
 
 
608
 
                /* parse the current sub-expression of a statement and fill up 
609
 
                 * ExpressionResult object
610
 
                 */
611
 
                result = parseExpression (current_token);
612
 
                
613
 
                if (process_res == false || curr_searchable_scope == NULL)
614
 
                {
615
 
                        DEBUG_PRINT ("No luck with the NEXT token, the NEXT token failed and then "
616
 
                                "I cannot continue. ");
617
 
 
618
 
                        if (curr_searchable_scope != NULL)
619
 
                                g_object_unref (curr_searchable_scope );
620
 
                        return NULL;
621
 
                }
622
 
                
623
 
                /* check if the name of the result is valuable or not */
624
 
                IAnjutaSymbol *node;
625
 
                IAnjutaIterable * iter;
626
 
 
627
 
                node = IANJUTA_SYMBOL (curr_searchable_scope);
628
 
                
629
 
                iter = ianjuta_symbol_query_search_in_scope (_query_search_in_scope,
630
 
                                                             result.m_name.c_str (),
631
 
                                                             node, NULL);
632
 
                
633
 
                if (iter == NULL)
634
 
                {
635
 
                        DEBUG_PRINT ("Warning, the result.m_name %s "
636
 
                                "does not belong to scope (id %d)", result.m_name.c_str (), 
637
 
                                     ianjuta_symbol_get_int (node, IANJUTA_SYMBOL_FIELD_ID, NULL));
638
 
                        
639
 
                        if (curr_searchable_scope != NULL)
640
 
                                g_object_unref (curr_searchable_scope );
641
 
                        
642
 
                        return NULL;
643
 
                }
644
 
                else 
645
 
                {
646
 
                        gchar *sym_kind;
647
 
                        DEBUG_PRINT ("Good element %s", result.m_name.c_str ());
648
 
                        
649
 
                        node = IANJUTA_SYMBOL (iter);
650
 
                        sym_kind = (gchar*)ianjuta_symbol_get_string (node, 
651
 
                                                                                                IANJUTA_SYMBOL_FIELD_KIND, NULL);
652
 
                        
653
 
                        DEBUG_PRINT (".. it has sym_kind \"%s\"", sym_kind);
654
 
 
655
 
                        /* the same check as in the engine-core on sdb_engine_add_new_sym_type () */
656
 
                        if (g_strcmp0 (sym_kind, "member") == 0 || 
657
 
                        g_strcmp0 (sym_kind, "variable") == 0 || 
658
 
                        g_strcmp0 (sym_kind, "field") == 0)
659
 
                        {
660
 
                                iter = switchMemberToContainer (iter);
661
 
                                node = IANJUTA_SYMBOL (iter);
662
 
                                sym_kind = (gchar*)ianjuta_symbol_get_string (node, 
663
 
                                                                                                IANJUTA_SYMBOL_FIELD_KIND, NULL);                               
664
 
                        }
665
 
                        
666
 
                        /* check for any typedef */
667
 
                        if (g_strcmp0 (ianjuta_symbol_get_string (node, 
668
 
                                                                                                IANJUTA_SYMBOL_FIELD_KIND, NULL),
669
 
                                                                                                "typedef") == 0)
670
 
                        {                       
671
 
                                iter = switchTypedefToStruct (iter);
672
 
                                node = IANJUTA_SYMBOL (iter);
673
 
                                sym_kind = (gchar*)ianjuta_symbol_get_string (node, 
674
 
                                                                                                IANJUTA_SYMBOL_FIELD_KIND, NULL);                               
675
 
                        }
676
 
                        
677
 
                        /* is it a function or a method? */
678
 
                        if (g_strcmp0 (sym_kind, "function") == 0 ||
679
 
                            g_strcmp0 (sym_kind, "method") == 0 ||
680
 
                            g_strcmp0 (sym_kind, "prototype") == 0)
681
 
                        {
682
 
 
683
 
                                string func_ret_type_name = 
684
 
                                        ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_RETURNTYPE, NULL);
685
 
 
686
 
                                string func_signature = 
687
 
                                        ianjuta_symbol_get_string (node, IANJUTA_SYMBOL_FIELD_SIGNATURE, NULL);
688
 
                                
689
 
                                func_ret_type_name += " " + result.m_name + func_signature + "{}";
690
 
 
691
 
                                FunctionList li;
692
 
                                std::map<std::string, std::string> ignoreTokens;
693
 
                                get_functions (func_ret_type_name, li, ignoreTokens);
694
 
 
695
 
                                DEBUG_PRINT ("Functions found are...");
696
 
/*                              
697
 
                                for (FunctionList::reverse_iterator func_iter = li.rbegin(); 
698
 
                                     func_iter != li.rend(); 
699
 
                                     func_iter++) 
700
 
                                {
701
 
                                        Function var = (*func_iter);
702
 
                                        var.print ();                   
703
 
                                }
704
 
*/
705
 
                        
706
 
                                g_object_unref (iter);
707
 
 
708
 
                                DEBUG_PRINT ("Going to look for the following function ret type %s",
709
 
                                                        func_ret_type_name.c_str ());
710
 
 
711
 
                                iter = getCurrentSearchableScope (li.front().m_returnValue.m_type,
712
 
                                                                  type_scope);
713
 
                        }                                      
714
 
                        
715
 
                        /* remove the 'old' curr_searchable_scope and replace with 
716
 
                         * this new one
717
 
                         */                     
718
 
                        g_object_unref (curr_searchable_scope);                 
719
 
                        curr_searchable_scope = iter;
720
 
                        continue;
721
 
                }
722
 
        }
723
 
 
724
 
        DEBUG_PRINT ("END of expression processing. Returning curr_searchable_scope");
725
 
        return curr_searchable_scope;
726
 
}
727
 
 
728
 
/**
729
 
 * @return The visible scope until pchStopWord is encountered
730
 
 */
731
 
string 
732
 
EngineParser::optimizeScope(const string& srcString)
733
 
{
734
 
        string wxcurrScope;
735
 
        std::vector<std::string> scope_stack;
736
 
        std::string currScope;
737
 
 
738
 
        int type;
739
 
 
740
 
        /* Initialize the scanner with the string to search */
741
 
        const char * scannerText =  srcString.c_str ();
742
 
        _extra_tokenizer->setText (scannerText);
743
 
        bool changedLine = false;
744
 
        bool prepLine = false;
745
 
        int curline = 0;
746
 
        while (true) 
747
 
        {
748
 
                type = _extra_tokenizer->yylex();
749
 
 
750
 
                /* Eof ? */
751
 
                if (type == 0) 
752
 
                {
753
 
                        if (!currScope.empty())
754
 
                                scope_stack.push_back(currScope);
755
 
                        break;
756
 
                }
757
 
 
758
 
                /* eat up all tokens until next line */
759
 
                if ( prepLine && _extra_tokenizer->lineno() == curline) 
760
 
                {
761
 
                        currScope += " ";
762
 
                        currScope += _extra_tokenizer->YYText();
763
 
                        continue;
764
 
                }
765
 
 
766
 
                prepLine = false;
767
 
 
768
 
                /* Get the current line number, it will help us detect preprocessor lines */
769
 
                changedLine = (_extra_tokenizer->lineno() > curline);
770
 
                if (changedLine) 
771
 
                {
772
 
                        currScope += "\n";
773
 
                }
774
 
 
775
 
                curline = _extra_tokenizer->lineno();
776
 
                switch (type) 
777
 
                {
778
 
                case (int)'(':
779
 
                        currScope += "\n";
780
 
                        scope_stack.push_back(currScope);
781
 
                        currScope = "(\n";
782
 
                        break;
783
 
                case (int)'{':
784
 
                        currScope += "\n";
785
 
                        scope_stack.push_back(currScope);
786
 
                        currScope = "{\n";
787
 
                        break;
788
 
                case (int)')':
789
 
                        // Discard the current scope since it is completed
790
 
                        if ( !scope_stack.empty() ) {
791
 
                                currScope = scope_stack.back();
792
 
                                scope_stack.pop_back();
793
 
                                currScope += "()";
794
 
                        } else
795
 
                                currScope.clear();
796
 
                        break;
797
 
                case (int)'}':
798
 
                        /* Discard the current scope since it is completed */
799
 
                        if ( !scope_stack.empty() ) {
800
 
                                currScope = scope_stack.back();
801
 
                                scope_stack.pop_back();
802
 
                                currScope += "\n{}\n";
803
 
                        } else {
804
 
                                currScope.clear();
805
 
                        }
806
 
                        break;
807
 
                case (int)'#':
808
 
                        if (changedLine) {
809
 
                                /* We are at the start of a new line
810
 
                                 * consume everything until new line is found or end of text
811
 
                                 */
812
 
                                currScope += " ";
813
 
                                currScope += _extra_tokenizer->YYText();
814
 
                                prepLine = true;
815
 
                                break;
816
 
                        }
817
 
                default:
818
 
                        currScope += " ";
819
 
                        currScope += _extra_tokenizer->YYText();
820
 
                        break;
821
 
                }
822
 
        }
823
 
 
824
 
        _extra_tokenizer->reset();
825
 
 
826
 
        if (scope_stack.empty())
827
 
                return srcString;
828
 
 
829
 
        currScope.clear();
830
 
        size_t i = 0;
831
 
        for (; i < scope_stack.size(); i++)
832
 
                currScope += scope_stack.at(i);
833
 
 
834
 
        /* if the current scope is not empty, terminate it with ';' and return */
835
 
        if ( currScope.empty() == false ) {
836
 
                currScope += ";";
837
 
                return currScope.c_str();
838
 
        }
839
 
 
840
 
        return srcString;
841
 
}
842
 
 
843
 
/************ C FUNCTIONS ************/
844
 
 
845
 
void
846
 
engine_parser_init (IAnjutaSymbolManager * manager)
847
 
{
848
 
        EngineParser::getInstance ()->setSymbolManager (manager);
849
 
}
850
 
 
851
 
void
852
 
engine_parser_deinit ()
853
 
{
854
 
        EngineParser::getInstance ()->unsetSymbolManager ();
855
 
}
856
 
 
857
 
IAnjutaIterable *
858
 
engine_parser_process_expression (const gchar *stmt, const gchar * above_text,
859
 
    const gchar * full_file_path, gulong linenum)
860
 
{
861
 
        try
862
 
        {
863
 
                IAnjutaIterable *iter = 
864
 
                        EngineParser::getInstance ()->processExpression (stmt, 
865
 
                                                                         above_text,  
866
 
                                                                         full_file_path, 
867
 
                                                                         linenum);
868
 
                return iter;
869
 
        }
870
 
        catch (const std::exception& error)
871
 
        {
872
 
                g_critical ("cxxparser error: %s", error.what());
873
 
                return NULL;
874
 
        }
875
 
}