~ubuntu-branches/ubuntu/natty/aspectc++/natty

« back to all changes in this revision

Viewing changes to Puma/src/manip/CTreeMatcher.cc

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-12-23 10:49:40 UTC
  • Revision ID: james.westby@ubuntu.com-20051223104940-ig4klhoi991zs7km
Tags: upstream-0.99+1.0pre2
ImportĀ upstreamĀ versionĀ 0.99+1.0pre2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This file is part of PUMA.
 
2
// Copyright (C) 1999-2003  The PUMA developer team.
 
3
//                                                                
 
4
// This program is free software;  you can redistribute it and/or 
 
5
// modify it under the terms of the GNU General Public License as 
 
6
// published by the Free Software Foundation; either version 2 of 
 
7
// the License, or (at your option) any later version.            
 
8
//                                                                
 
9
// This program is distributed in the hope that it will be useful,
 
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
 
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 
12
// GNU General Public License for more details.                   
 
13
//                                                                
 
14
// You should have received a copy of the GNU General Public      
 
15
// License along with this program; if not, write to the Free     
 
16
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 
17
// MA  02111-1307  USA                                            
 
18
 
 
19
#include "Puma/CTranslationUnit.h"
 
20
#include "Puma/CTreeMatcher.h"
 
21
#include "Puma/CMatchChecker.h"
 
22
//#include "Puma/CRankTable.h"
 
23
#include "Puma/RegComp.h"
 
24
#include "Puma/CTree.h"
 
25
#include "Puma/StrCol.h"
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
namespace Puma {
 
30
 
 
31
 
 
32
void CTreeMatcher::init (CTree *matchTree, unsigned int max) {
 
33
  _max_mobjs = max;
 
34
  _num_mobjs = 0;
 
35
    
 
36
  // Set the current match tree.
 
37
  _matchTree = matchTree;
 
38
}
 
39
 
 
40
void CTreeMatcher::pre_visit (CTree *node) {
 
41
  // Do nothing on visit if no match tree is given.
 
42
  if (! _matchTree || ! node) 
 
43
    return;
 
44
 
 
45
  // Check whether this node is really the expected node and not  
 
46
  // maybe someone that only looks like it.
 
47
  if (! correct (node))
 
48
    return;
 
49
 
 
50
  // If the match tree can't be a sub tree of the current C++ syntax
 
51
  // tree node, trying to match this node and its sons is skipped. 
 
52
//  if (CRankTable::Rank (node->astName ()) < 
 
53
//      CRankTable::Rank (_matchTree->astName ()))
 
54
//    return;
 
55
 
 
56
  // Create CMatch object and add the current node to it.
 
57
  CMatch *matchObj = new CMatch;
 
58
  matchObj->add (node, "root");
 
59
    
 
60
  // If the current sub-tree is matching the match tree, call 
 
61
  // action() with the current node and the nodes that correspond 
 
62
  // with the any-nodes of the match tree as arguments. 
 
63
  if (match (node, _matchTree, matchObj)) {
 
64
    _num_mobjs++;
 
65
    action (matchObj);
 
66
    if (_max_mobjs <= _num_mobjs && _max_mobjs != 0)
 
67
      abort (); // Abort traversing the syntax tree!
 
68
  } 
 
69
  // Not matching. Delete the match object.
 
70
  else
 
71
    delete matchObj;
 
72
}
 
73
 
 
74
// Return true if the current sub-tree is matching the match tree.
 
75
bool CTreeMatcher::match (CTree *currTree, CTree *matchTree, 
 
76
                          CMatch* matchObj) const {
 
77
  if (! currTree || ! matchTree || ! matchObj)
 
78
    return false;
 
79
 
 
80
  // Don't compare against CT_ImplicitCast nodes.
 
81
  while (currTree->NodeName () == CT_ImplicitCast::NodeId ())
 
82
    currTree = currTree->Son (0);
 
83
 
 
84
  // The current node of the match tree is an Any node. 
 
85
  if (matchTree->NodeName () == CT_Any::NodeId () || 
 
86
      matchTree->NodeName () == CT_AnyList::NodeId ()) {
 
87
    CT_AnyExtension *ext = ((CT_Any*)matchTree)->Extension ();
 
88
    CTree *condition = ext ? ext->Condition () : (CTree*)0;
 
89
    const char *name = ext ? ext->Name () : (const char*)0;
 
90
    Array<CTree *> *old = &matchObj->get (name);
 
91
 
 
92
    // If there already is an Any node with that name, it has
 
93
    // to be checked whether the two trees are the same.
 
94
    if (old->length ())
 
95
      if (! match (old->get (0), currTree, matchObj))
 
96
        return false;
 
97
 
 
98
    // If there is no extra condition for matching with this 
 
99
    // any-node, the current tree node always is matching.
 
100
    if (condition) {
 
101
      int mode = 0;
 
102
            
 
103
      // Tell the match-parser which condition keywords are allowed.
 
104
      if (matchTree->NodeName () == CT_Any::NodeId ())
 
105
        mode = ANY;
 
106
      else if (matchTree->NodeName () == CT_AnyList::NodeId ())
 
107
        mode = ANY_LIST;
 
108
 
 
109
      if (! evalMatchCondition (currTree, condition, matchObj, mode))
 
110
        return false;
 
111
    }
 
112
 
 
113
    // Remember anys with a name only.
 
114
    if (name)
 
115
      matchObj->add (currTree, name);
 
116
            
 
117
    return true;
 
118
  } 
 
119
 
 
120
  // If the current node of the match tree isn't an any-node 
 
121
  // the two current nodes must be of the same type and must 
 
122
  // have the same number of sons.
 
123
  if (currTree->NodeName () != matchTree->NodeName () ||   
 
124
      currTree->Sons () != matchTree->Sons ())   
 
125
    return false;
 
126
        
 
127
  // The current nodes are tokens. The text of the tokens 
 
128
  // must be the same.
 
129
  if (currTree->NodeName () == CT_Token::NodeId ()) {
 
130
    if (! currTree->token () || ! matchTree->token ())
 
131
      return false;
 
132
    if (! currTree->token ()->text () || ! matchTree->token ()->text ())
 
133
      return false;
 
134
    if (strcmp (currTree->token ()->text (),
 
135
                matchTree->token ()->text ()) != 0)
 
136
      return false;
 
137
  } 
 
138
    
 
139
  // Now call match() for every son of the current node.
 
140
  for (int i = 0; i < currTree->Sons (); i++)
 
141
    if (! match (currTree->Son (i), matchTree->Son (i), matchObj))
 
142
      return false;
 
143
 
 
144
  // The current C++ sub-tree is matching the current sub-tree 
 
145
  // of the match tree.
 
146
  return true;
 
147
}
 
148
 
 
149
// Match any node-list. 
 
150
int CTreeMatcher::matchList (int mode, match_state &mstate, 
 
151
                             CTree *mt, CTree *f, CTree *l) const {
 
152
  bool matched = false;
 
153
  CT_List *list = (CT_List*)mstate.tree;
 
154
  int elements = list->Entries ();
 
155
  int sign_f = 0, sign_l = 0;
 
156
 
 
157
  if (f) {
 
158
    sign_f = (f->token ()->text ().c_str ()[0] == '-') ? -1 : 1;
 
159
    f = f->Son (f->Sons () - 1);
 
160
  }
 
161
  if (l) {
 
162
    sign_l = (l->token ()->text ().c_str ()[0] == '-') ? -1 : 1;
 
163
    l = l->Son (l->Sons () - 1);
 
164
  }
 
165
 
 
166
  // Get the arguments.
 
167
  int first = (f) ? (sign_f * (int) strtol (f->token ()->text (), NULL, 10)) : 1;
 
168
  int last  = (l) ? (sign_l * (int) strtol (l->token ()->text (), NULL, 10)) : elements;
 
169
    
 
170
  // Compute the real element number.
 
171
  if (first < 0) first = elements + first + 1;
 
172
  if (last  < 0) last  = elements + last  + 1;
 
173
 
 
174
  // Wrong arguments?
 
175
  if (first <= 0 || last <= 0) 
 
176
    return 0;
 
177
    
 
178
  // The current list has too few elements.
 
179
  if (first > elements || last > elements)
 
180
    return 0;
 
181
        
 
182
  // If the two arguments have the same value, the user wanted
 
183
  // to match lists that have exact the given number of elements.
 
184
  if (first == last && f && l) {
 
185
    if (first != elements)
 
186
      return 0;
 
187
            
 
188
    first = 1;
 
189
    last  = elements;
 
190
  }
 
191
 
 
192
  // Match a single element.
 
193
  if (f && ! l)
 
194
    last = first;
 
195
    
 
196
  // Match the list elements.
 
197
  for (int i = first; i <= last; i++)
 
198
    if (matchTree (mode, mstate, list->Entry (i - 1), mt))
 
199
      matched = true;
 
200
            
 
201
  // Return the success value.
 
202
  return matched ? 1 : 0;
 
203
}
 
204
 
 
205
// Match any node. 
 
206
int CTreeMatcher::matchTree (int mode, match_state &mstate, CTree *tree,
 
207
                             CTree *mt) const {
 
208
  int matched = 0;
 
209
  CMatch tmp;
 
210
 
 
211
  if (mode == MATCH_ALL || 
 
212
      mode == MATCH_FIRST || 
 
213
      mode == MATCH_LAST ||
 
214
      mode == MATCH_PRUNE || 
 
215
      mode == MATCH_LEAF) {
 
216
    CMatchChecker check (mode, mt, &tmp);
 
217
    check.visit (tree);
 
218
    matched = (check.matchFound ()) ? 1 : 0;
 
219
  } 
 
220
  else if (mode == MATCH_EXACT) 
 
221
    matched = (match (tree, mt, &tmp)) ? 1 : 0;
 
222
 
 
223
  // Remember all the matches.
 
224
  if (matched) 
 
225
    mstate.matchObj->combine (&tmp);
 
226
    
 
227
  return matched;
 
228
}
 
229
 
 
230
// Match a node by its name. Regular expressions are allowed.
 
231
int CTreeMatcher::matchNodeName (CTree *tree, CTree *mt) const {
 
232
  if (! mt || ! tree) 
 
233
    return 0;
 
234
  if (mt->NodeName () != CT_String::NodeId ())
 
235
    return 0;
 
236
 
 
237
  char *string = StrCol::dup (mt->token ()->text ().c_str () + 1);
 
238
  string[strlen (string) - 1] = '\0';
 
239
    
 
240
  RegComp compare (string);
 
241
  bool matching = compare.match ((const char*)tree->NodeName ());
 
242
  delete[] string;
 
243
  return matching ? 1 : 0;
 
244
}
 
245
 
 
246
// Start the match process.
 
247
void CTreeMatcher::match (CTranslationUnit &tUnit, 
 
248
                          CTranslationUnit &matchUnit, CTree *syntaxtree) {
 
249
  // Do the manipulations only if there really is a syntax tree.
 
250
  CTree *matchtree = matchUnit.tree ();
 
251
  if (! syntaxtree) 
 
252
    syntaxtree = tUnit.tree ();
 
253
  if (syntaxtree) {
 
254
    init (matchtree);
 
255
//    tUnit.cppTree ()->context ().push ();
 
256
    visit (syntaxtree);
 
257
//    tUnit.cppTree ()->context ().pop ();
 
258
  }
 
259
}
 
260
 
 
261
 
 
262
} // namespace Puma