19
19
#include "Puma/ACIntroAnalyzer.h"
20
20
#include "Puma/CClassDatabase.h"
21
#include "Puma/CCNameLookup.h"
21
22
#include "Puma/CScopeInfo.h"
22
23
#include "Puma/CTokens.h"
23
24
#include <string.h>
28
CScopeInfo *_current_scope;
28
int ACIntroAnalyzer::ttype(int pos) {
32
29
return _intro->Entry (pos)->token ()->type ();
35
bool is_in (int tok, int *set) {
32
bool ACIntroAnalyzer::is_in (int tok, int *set) {
111
bool nested_name (int &outer_pos, bool &is_declarator, bool is_decl_name = false) {
108
bool ACIntroAnalyzer::nested_name (int &outer_pos, bool &is_declarator,
112
111
// save the current position
113
112
int pos = outer_pos;
115
114
// by default this name is not necessarily part of the declarator
116
115
is_declarator = false;
117
// scope is 0 at the beginning
118
CScopeInfo *last_scope = 0;
118
120
// root qualified name ("::" is optional)?
119
121
bool root = false;
122
CScopeInfo *lookup_scope = _current_scope;
123
CScopeInfo *relevant_scope = 0;
120
124
if (ttype (pos) == TOK_COLON_COLON) {
127
while (!lookup_scope->GlobalScope ())
128
lookup_scope = lookup_scope->Parent ();
129
last_scope = lookup_scope;
133
int relevant_name_index = -1;
126
134
bool is_destructor = false;
127
bool is_in_aspect = false;
142
149
is_destructor = true;
144
151
else if (tok == TOK_ID) {
153
CCNameLookup nl (err);
154
nl.lookup (_intro->Entry (pos)->token ()->text (),
155
lookup_scope->Structure (), !last_scope);
156
CObjectInfo *obj = nl.Objects () ? nl.Object (0) : (CObjectInfo*)0;
157
if (obj && obj->ScopeInfo ()) {
158
if (!relevant_scope && ((_is_slice && _db->SliceInfo (obj)) ||
159
(!_is_slice && is_decl_name && obj->ClassInfo () &&
160
_db->AspectInfo (obj->ClassInfo ())))) {
161
relevant_scope = obj->ScopeInfo ();
162
relevant_name_index = pos;
147
167
tok = ttype (pos);
148
168
if (tok == TOK_COLON_COLON) {
149
if (names == 1 && is_decl_name &&
150
_db->AspectInfo (_intro->Entry (pos - 1)->token ()->text ())) {
151
_intro->AddNameIndex (pos - 1);
169
if (obj && obj->ScopeInfo ()) {
170
lookup_scope = obj->ScopeInfo ();
171
last_scope = lookup_scope;
167
186
} while (!done && pos < _intro->Entries ());
169
if (!root && pos >= 1 && names == 1 && _current_scope->ClassInfo () &&
170
strcmp (_current_scope->Name (),
171
_intro->Entry (pos - 1)->token ()->text ()) == 0) {
172
int name_pos = pos - 1;
173
if (constructor_args (pos)) {
174
is_declarator = true;
175
// store the detected name in the CT_Intro object
177
_intro->AddNameIndex (name_pos);
181
// qualified constructor name?
182
else if (pos >= 3 && names >= 2 && !_current_scope->ClassInfo () &&
183
strcmp (_intro->Entry (pos - 1)->token ()->text (),
184
_intro->Entry (pos - 3)->token ()->text ()) == 0) {
185
is_declarator = true;
186
// store the detected name in the CT_Intro object
187
if (is_decl_name && names == 2) {
188
_intro->AddNameIndex (pos - 1);
191
// qualified destructor name?
192
else if (pos >= 4 && names >= 2 && !_current_scope->ClassInfo () &&
194
strcmp (_intro->Entry (pos - 1)->token ()->text (),
195
_intro->Entry (pos - 4)->token ()->text ()) == 0) {
196
is_declarator = true;
197
// store the detected name in the CT_Intro object
198
if (is_decl_name && names == 2) {
199
_intro->AddNameIndex (pos - 1);
203
is_declarator = false;
188
if (relevant_name_index >= 0) {
189
_intro->AddNameIndex (outer_pos, relevant_name_index);
194
// qualified constructor name?
195
const DString &last_name = _intro->Entry (pos - 1)->token ()->text ();
196
if (last_name == _intro->Entry (pos - 3)->token ()->text ()) {
197
is_declarator = true;
199
// qualified destructor name?
200
else if (is_destructor &&
201
last_name == _intro->Entry (pos - 4)->token ()->text ()) {
202
is_declarator = true;
204
if (is_declarator && is_decl_name &&
205
relevant_scope && last_name == relevant_scope->Name ()) {
206
// store the detected name in the CT_Intro object
207
_intro->AddNameIndex (pos - 1);
205
211
if (is_destructor)
206
212
is_declarator = true;
208
if (names && !(!is_decl_name && is_declarator))
214
if (names && !(!is_decl_name && is_declarator)) {
215
if (relevant_scope) {
216
if (_intro->Scope () && relevant_scope != _intro->Scope ())
218
_intro->Scope (relevant_scope->Structure ());
210
223
return (names > 0);
214
bool ptr_operator (int &outer_pos) {
227
bool ACIntroAnalyzer::ptr_operator (int &outer_pos) {
215
228
// save the current position
216
229
int pos = outer_pos;
256
bool declarator (int &outer_pos) {
269
bool ACIntroAnalyzer::declarator (int &outer_pos) {
257
270
int term[] = { TOK_COMMA, TOK_ASSIGN, TOK_OPEN_CURLY, TOK_SEMI_COLON,
258
271
TOK_CLOSE_ROUND, 0 };
259
272
// save the current position
305
void ACIntroAnalyzer::analyze (CClassDatabase *db, CScopeInfo *current_scope,
318
const char *ACIntroAnalyzer::error_msg () const {
320
case IA_OK: return "no error in introduction";
321
case IA_UNDEFINED: return "introduction not analyzed";
322
case IA_INVALID: return "invalid introduction";
323
case IA_INV_SCOPE: return "introduction definition not in aspect scope";
324
case IA_INV_SLICE: return "invalid slice declaration";
325
case IA_INV_DESTR: return "invalid destructor name";
326
case IA_SLICE_IN_SLICE: return "slice in slice definition";
327
case IA_ASPECT_IN_SLICE: return "aspect in slice definition";
328
case IA_ADVICE_IN_SLICE: return "advice in slice definition";
329
case IA_PCT_IN_SLICE: return "pointcut in slice definition";
335
void ACIntroAnalyzer::analyze_intro_member (CT_Intro *intro) {
341
// check for constructor
343
if (ttype (pos) == TOK_EXPLICIT)
345
if (ttype (pos) == TOK_ID &&
346
_intro->Entry (pos)->token ()->text () == _current_scope->Name ()) {
349
if (constructor_args (pos)) {
350
_intro->AddNameIndex (name_pos);
354
// check for destructor
356
if (ttype (pos) == TOK_VIRTUAL)
358
if (ttype (pos) == TOK_TILDE) {
360
if (ttype (pos) == TOK_ID &&
361
_intro->Entry (pos)->token ()->text () == _current_scope->Name ()) {
364
if (ttype (pos) == TOK_OPEN_ROUND && ttype (pos + 1) == TOK_CLOSE_ROUND) {
365
_intro->AddNameIndex (name_pos);
369
_state = IA_INV_DESTR;
374
for (pos = 0; pos < _intro->Entries () && _state == IA_OK; pos++) {
375
int tok = ttype (pos);
376
if (tok == TOK_SLICE)
377
_state = IA_SLICE_IN_SLICE;
378
else if (tok == TOK_ASPECT)
379
_state = IA_ASPECT_IN_SLICE;
380
else if (tok == TOK_ADVICE)
381
_state = IA_ADVICE_IN_SLICE;
382
else if (tok == TOK_POINTCUT)
383
_state = IA_PCT_IN_SLICE;
387
void ACIntroAnalyzer::analyze_intro (CT_Intro *intro) {
308
389
// should become attributes
310
_current_scope = current_scope;
391
_is_slice = (intro->token ()->type () == TOK_SLICE);
313
393
_state = IA_INVALID;
316
396
// skip the declaration specifier sequence
318
398
bool have_type = false;
394
// first case: we are in an aspect body
395
if (current_scope->ClassInfo ()) {
396
_scope = db->AspectInfo (current_scope->ClassInfo ());
398
else if (current_scope->GlobalScope () &&
399
_intro->NameIndices () > 0) {
400
// second case: a non-inline introduction defined in global scope
401
int index = _intro->NameIndex (0);
402
_scope = _db->AspectInfo (_intro->Entry (index)->token ()->text ());
405
475
//if we were able to determine the scope, the result is valid
407
// cout << "INTRO" << endl;
476
// cout << "slice: " << _intro->token ()->location () << endl;
477
if (_intro->Scope ()) {
408
479
// for (int e = 0; e < _intro->Entries (); e++)
409
480
// cout << _intro->Entry (e)->token ()->text () << " ";
411
// for (int i = 0; i < _intro->NameIndices (); i++)
412
// cout << _intro->NameIndex (i) << " ";
482
// cout << " => indices: ";
483
// for (int i = 0; i < _intro->NameIndices (); i++) {
484
// cout << "(" << _intro->NameIndex (i) << "," << _intro->NameToIndex (i);
485
// if (_intro->NameQual (i))
490
// cout << " => scope: " << _intro->Scope ()->QualName () << endl;